Script 8 for Kitchel et al.Ā 2024 in prep taxonomic diversity
manuscript.
library(data.table)
library(MuMIn)
library(ggplot2)
library(cowplot)
library(lme4)
library(stringr)
###Predicts annual dissimilarity with annual characteristics,
temperature and fishing values
Pull in - region areas (if not already loaded) - region
characteristics (if not already loaded);
saveRDS(FishGlob_richness_year_survey, file =
here::here(āoutputā,āFishGlob_richness_year_survey.Rdsā)) - fishing (if
not already loaded) - temp (if not already loaded)
#physical area by year
region_area_byyear <- fread(here::here("output","region_area_byyear.csv"))
#merged fishing, temp, dissimilarities
dissimilarities_temp_fishing <- fread(here::here("output","dissimilarities_temp_fishing.csv"))
#combine
dissimilarities_temp_fishing_area <- dissimilarities_temp_fishing[region_area_byyear, on = c("survey_unit","year")]
#only jaccard for these analyses
dissimilarities_temp_fishing_area.jaccard <- dissimilarities_temp_fishing_area[dissimilarity_metric == "jaccard_dissimilarity_total",]
Add in average Julian day
#load up julian days
dates_regions <- readRDS(here::here("output","dates_regions.rds"))
#simplify
dates_regions.annual <- unique(dates_regions[,.(survey_unit, year, avg_julian_annual)])
#merge
dissimilarities_temp_fishing_area.jaccard <- dates_regions.annual[dissimilarities_temp_fishing_area.jaccard, on = c("survey_unit","year")]
Pull in palette and name helper
source(here::here("analysis_code","color_links.R"))
Pull in observed trend values
jaccard_total_coefs.r <- fread(here::here("output","jaccard_total_coefs.r.csv"))
Plot fishing and temperature vs.Ā time for all regions
#######TEMPERATURE
#set order by survey unit for plotting
all_surveys <- levels(as.factor(dissimilarities_temp_fishing_area.jaccard$survey_unit))
setorder(dissimilarities_temp_fishing_area.jaccard, survey_unit)
dissimilarities_temp_fishing_area.jaccard[,Survey_Name_Season:=factor(Survey_Name_Season, levels = unique(dissimilarities_temp_fishing_area.jaccard$Survey_Name_Season), ordered = T)]
(sbt_time_survey_facet_1_20 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[1:20] & year > 1979]) +
labs(y = "Mean bottom temperature (ĖC)", x = "Year") +
geom_point(aes(y = as.numeric(yearly_mean_bypoint_avg), x = year), alpha = 0.3) +
geom_smooth(aes(y = as.numeric(yearly_mean_bypoint_avg), x = year), method = "lm") +
scale_x_continuous(breaks = ~ axisTicks(., log = FALSE)) +
theme_classic() +
theme(axis.text.x = element_text(size = 7)) +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4))
ggsave(sbt_time_survey_facet_1_20, path = here::here("figures"), filename = "temp_time_survey_facet_1_20.jpg", height = 12, width =9)

(sbt_time_survey_facet_21_34 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[21:34] & year > 1979]) +
labs(y = "Mean bottom temperature (ĖC)", x = "Year") +
geom_point(aes(y = as.numeric(yearly_mean_bypoint_avg), x = year), alpha = 0.3) +
geom_smooth(aes(y = as.numeric(yearly_mean_bypoint_avg), x = year), method = "lm") +
scale_x_continuous(breaks = ~ axisTicks(., log = FALSE)) +
theme_classic() +
theme(axis.text.x = element_text(size = 7)) +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4))
ggsave(sbt_time_survey_facet_21_34, path = here::here("figures"), filename = "sbt_time_survey_facet_21_34.jpg", height = 12, width =9)

#######FISHING
dissimilarities_temp_fishing_area.jaccard.cc <- dissimilarities_temp_fishing_area.jaccard[complete.cases(dissimilarities_temp_fishing_area.jaccard[,summed_tonnes_scaled_byreg]),]
(fishing_time_survey_facet_1_20 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard.cc[survey_unit %in% all_surveys[1:20] & year > 1979]) +
labs(y = "Relative fishing catch", x = "Year") +
geom_point(aes(y = summed_tonnes_scaled_byreg, x = year), alpha = 0.3) +
geom_smooth(aes(y = summed_tonnes_scaled_byreg, x = year), method = "lm") +
scale_x_continuous(breaks = ~ axisTicks(., log = FALSE)) +
theme_classic() +
theme(axis.text.x = element_text(size = 7)) +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4))
ggsave(fishing_time_survey_facet_1_20, path = here::here("figures"), filename = "fishing_time_survey_facet_1_20.jpg", height = 12, width =9)

(fishing_time_survey_facet_21_34 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard.cc[survey_unit %in% all_surveys[c(21:34)] & year > 1979]) +
labs(y = "Relative fishing catch", x = "Year") +
geom_point(aes(y = summed_tonnes_scaled_byreg, x = year), alpha = 0.3) +
geom_smooth(aes(y = summed_tonnes_scaled_byreg, x = year), method = "lm") +
scale_x_continuous(breaks = ~ axisTicks(., log = FALSE)) +
theme_classic() +
theme(axis.text.x = element_text(size = 7)) +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4))
ggsave(fishing_time_survey_facet_21_34, path = here::here("figures"), filename = "fishing_time_survey_facet_21_34.jpg", height = 12, width =9)

NA
NA
Plot fishing and temperature vs.Ā dissimilarity for all regions
#####MEAN TEMP
(preds_sbt_mean_temp_survey_facet_1_20 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[1:20] & year > 1979]) +
labs(x = "Mean bottom temperature (ĖC)", y = "β-diversity") +
geom_point(aes(x = as.numeric(yearly_mean_bypoint_avg), y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = as.numeric(yearly_mean_bypoint_avg), y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_mean_temp_survey_facet_1_20, path = here::here("figures"), filename = "preds_sbt_mean_temp_survey_facet_1_20.jpg", height = 12, width =9)

(preds_sbt_mean_temp_survey_facet_21_34 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[21:34] & year > 1979]) +
labs(x = "Mean bottom temperature (ĖC)", y = "β-diversity") +
geom_point(aes(x = as.numeric(yearly_mean_bypoint_avg), y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = as.numeric(yearly_mean_bypoint_avg), y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_mean_temp_survey_facet_21_34, path = here::here("figures"), filename = "preds_sbt_mean_temp_survey_facet_21_34.jpg", height = 12, width =9)

#####MINIMUM TEMP
(preds_sbt_min_temp_survey_facet_1_20 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[1:20] & year > 1979]) +
labs(x = "Minimum bottom temperature (ĖC)", y = "β-diversity") +
geom_point(aes(x = as.numeric(yearly_min_bypoint_avg), y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = as.numeric(yearly_min_bypoint_avg), y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_min_temp_survey_facet_1_20, path = here::here("figures"), filename = "preds_sbt_min_temp_survey_facet_1_20.jpg", height = 12, width =9)

(preds_sbt_min_temp_survey_facet_21_34 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard[survey_unit %in% all_surveys[21:34] & year > 1979]) +
labs(x = "Minimum bottom temperature (ĖC)", y = "β-diversity") +
geom_point(aes(x = as.numeric(yearly_min_bypoint_avg), y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = as.numeric(yearly_min_bypoint_avg), y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_min_temp_survey_facet_21_34, path = here::here("figures"), filename = "preds_sbt_min_temp_survey_facet_21_34.jpg", height = 12, width =9)

#######FISHING
dissimilarities_temp_fishing_area.jaccard.cc <- dissimilarities_temp_fishing_area.jaccard[complete.cases(dissimilarities_temp_fishing_area.jaccard[,summed_tonnes_scaled_byreg]),]
(preds_sbt_mean_fishing_survey_facet_1_20 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard.cc[survey_unit %in% all_surveys[1:20] & year > 1979]) +
labs(x = "Relative fishing catch", y = "β-diversity") +
geom_point(aes(x = summed_tonnes_scaled_byreg, y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = summed_tonnes_scaled_byreg, y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_mean_fishing_survey_facet_1_20, path = here::here("figures"), filename = "preds_sbt_mean_fishing_survey_facet_1_20.jpg", height = 12, width =9)

(preds_sbt_mean_fishing_survey_facet_21_34 <- ggplot(data = dissimilarities_temp_fishing_area.jaccard.cc[survey_unit %in% all_surveys[c(21:34)] & year > 1979]) +
labs(x = "Relative fishing catch", y = "β-diversity") +
geom_point(aes(x = summed_tonnes_scaled_byreg, y = annual_dissimilarity_value), alpha = 0.3) +
geom_smooth(aes(x = summed_tonnes_scaled_byreg, y = annual_dissimilarity_value), method = "lm") +
facet_wrap(~Survey_Name_Season, scales= "free", ncol = 4) +
theme_classic())
ggsave(preds_sbt_mean_fishing_survey_facet_21_34, path = here::here("figures"), filename = "preds_sbt_mean_fishing_survey_facet_21_34.jpg", height = 12, width =9)

NA
NA
###Plot number of tows per year per region
tows_year <- unique(dissimilarities_temp_fishing_area.jaccard[,.(survey_unit, haul_id_count_annual, area_km, year, Survey_Name_Season)])
min_haul_density <- min(tows_year$haul_id_count_annual/tows_year$area_km)
max_haul_density <- max(tows_year$haul_id_count_annual/tows_year$area_km)
(tow_density_survey_facet_1_20 <- ggplot(data = tows_year[survey_unit %in% all_surveys[1:20]]) +
labs(x = "Year", y = expression("Tow density (tows per km"^2*")")) +
geom_point(aes(x = year, y = haul_id_count_annual/area_km)) +
ylim(c(min_haul_density-0.0001, max_haul_density+0.0001)) +
facet_wrap(~Survey_Name_Season, ncol = 4) +
theme_classic())
ggsave(tow_density_survey_facet_1_20, path = here::here("figures"), filename = "tow_density_survey_facet_1_20.jpg", height = 12, width =9)

(tow_density_survey_facet_21_34 <- ggplot(data = tows_year[survey_unit %in% all_surveys[21:34]]) +
labs(x = "Year", y = expression("Tow density (tows per km"^2*")")) +
geom_point(aes(x = year, y = haul_id_count_annual/area_km)) +
ylim(c(min_haul_density-0.0001, max_haul_density+0.0001)) +
facet_wrap(~Survey_Name_Season, ncol = 4) +
theme_classic())
ggsave(tow_density_survey_facet_21_34, path = here::here("figures"), filename = "tow_density_survey_facet_21_34.jpg", height = 12, width =9)
#minimum and maximum dissimilarity value
min_dissimilarity <- min(dissimilarities_temp_fishing_area.jaccard$annual_dissimilarity_value)
max_dissimilarity <- max(dissimilarities_temp_fishing_area.jaccard$annual_dissimilarity_value)
#how does tow density vary with dissimilarity?
tow_density_dissimilarity_1_20 <-
ggplot(data = dissimilarities_temp_fishing_area.jaccard[dissimilarity_metric == "jaccard_dissimilarity_total" & survey_unit %in% all_surveys[1:20]]) +
geom_point(aes(x = (haul_id_count_annual/area_km), y = annual_dissimilarity_value, color = year), size = 2) +
viridis::scale_color_viridis() +
facet_wrap(~Survey_Name_Season, ncol = 4) +
labs(x = "Tow density (tows per km^2)", y = "β-diversity", color = "Year") +
xlim(c(min_haul_density-0.0001, max_haul_density+0.0001)) +
ylim(c(min_dissimilarity-0.01,max_dissimilarity+0.01)) +
theme_classic()
ggsave(tow_density_dissimilarity_1_20, path = here::here("figures"), filename = "tow_density_dissimilarity_1_20.jpg", height = 12, width =9)
tow_density_dissimilarity_21_34 <-
ggplot(data = dissimilarities_temp_fishing_area.jaccard[dissimilarity_metric == "jaccard_dissimilarity_total" & survey_unit %in% all_surveys[21:34]]) +
geom_point(aes(x = (haul_id_count_annual/area_km), y = annual_dissimilarity_value, color = year), size = 2) +
viridis::scale_color_viridis() +
facet_wrap(~Survey_Name_Season, ncol = 4) +
labs(x = "Tow density (tows per km^2)", y = "β-diversity", color = "Year") +
xlim(c(min_haul_density-0.0001, max_haul_density+0.0001)) +
ylim(c(min_dissimilarity-0.01,max_dissimilarity+0.01)) +
theme_classic()
ggsave(tow_density_dissimilarity_21_34, path = here::here("figures"), filename = "tow_density_dissimilarity_21_34.jpg", height = 12, width =9)

###Set up dredge to identify best performing models
options(na.action = "na.fail")
dissimilarity_covariates_dredge.dt <- dissimilarities_temp_fishing_area.jaccard[,.
(year, survey_unit,
yearly_mean_bypoint_avg, yearly_max_bypoint_avg, yearly_min_bypoint_avg,yearly_seas_bypoint_avg,
yearly_mean_bypoint_SD, yearly_max_bypoint_SD, yearly_min_bypoint_SD,yearly_seas_bypoint_SD,
yearly_mean_bypoint_avg.s, yearly_max_bypoint_avg.s, yearly_min_bypoint_avg.s,yearly_seas_bypoint_avg.s,
annual_dissimilarity_value,
haul_id_count_annual,
spp_count_annual, depth_annual_avg,
depth_annual_range, latitude_annual_avg,
latitude_annual_range, area_km, avg_julian_annual, summed_tonnes_scaled_byreg)]
#merge in with colors for plotting predictions by survey
dissimilarity_covariates_dredge.dt <- color_link[dissimilarity_covariates_dredge.dt, on = "survey_unit"]
#If NA for any covariate, delete row
View(dissimilarity_covariates_dredge.dt)
#Deleted:
#Before 1980 and after 2019
#Gulf of Saint Laurence South (no depth data)
#No clear SAU match for Rockall Plateau
dissimilarity_covariates_dredge.dt <- dissimilarity_covariates_dredge.dt[complete.cases(dissimilarity_covariates_dredge.dt)]
dissimilarity_covariates_dredge.dt[, yearly_mean_bypoint_avg.scaledacrossall := scale(yearly_mean_bypoint_avg)][, yearly_mean_bypoint_SD.scaledacrossall := scale(yearly_mean_bypoint_SD)][, yearly_min_bypoint_avg.scaledacrossall := scale(yearly_min_bypoint_avg)][, yearly_max_bypoint_avg.scaledacrossall := scale(yearly_max_bypoint_avg)][, yearly_seas_bypoint_avg.scaledacrossall := scale(yearly_seas_bypoint_avg)][,haul_id_count_annual.scaledacrossall := scale(haul_id_count_annual)][,spp_count_annual.scaledacrossall := scale(spp_count_annual)][,depth_annual_avg.scaledacrossall := scale(depth_annual_avg)][,depth_annual_range.scaledacrossall := scale(depth_annual_range)] [,latitude_annual_avg.scaledacrossall := scale(latitude_annual_avg)][,latitude_annual_range.scaledacrossall := scale(latitude_annual_range)][,area_km.scaledacrossall := scale(area_km)][,julian_scaled := scale(avg_julian_annual)]
- ###Full model
-
temp + survey_unit + fishing + area + latitude range + latitude average
+ depth range + depth average + spp count + # of hauls + julian day + AR
for year
For temperature, we will look at: -mean (scaled across all regions)
-max (scaled across all regions) -min (scaled across all regions) -seas
(scaled across all regions) -SD
Comparing temp variables AND the presence/absence of a temporal
autocorrelation term
global_mod_mean_temp_gls <- gls(annual_dissimilarity_value ~
survey_unit*yearly_mean_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
correlation = corAR1(form=~year | survey_unit),
data = dissimilarity_covariates_dredge.dt)
global_mod_mean_temp_lm <- lm(annual_dissimilarity_value ~
survey_unit*yearly_mean_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
data = dissimilarity_covariates_dredge.dt)
global_mod_max_temp_lm <- lm(annual_dissimilarity_value ~
survey_unit*yearly_max_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
data = dissimilarity_covariates_dredge.dt)
global_mod_max_temp_gls <-gls(annual_dissimilarity_value ~
survey_unit*yearly_max_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
correlation = corAR1(form=~year | survey_unit),
data = dissimilarity_covariates_dredge.dt)
global_mod_min_temp_lm <- lm(annual_dissimilarity_value ~
survey_unit*yearly_min_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
data = dissimilarity_covariates_dredge.dt)
global_mod_min_temp_gls <-gls(annual_dissimilarity_value ~
survey_unit*yearly_min_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
correlation = corAR1(form=~year | survey_unit),
data = dissimilarity_covariates_dredge.dt)
global_mod_seas_temp_lm <- lm(annual_dissimilarity_value ~
survey_unit*yearly_seas_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
data = dissimilarity_covariates_dredge.dt)
global_mod_seas_temp_gls <- gls(annual_dissimilarity_value ~
survey_unit*yearly_seas_bypoint_avg.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
correlation = corAR1(form=~year | survey_unit),
data = dissimilarity_covariates_dredge.dt)
global_mod_SD_temp_lm <- lm(annual_dissimilarity_value ~
survey_unit*yearly_mean_bypoint_SD.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
data = dissimilarity_covariates_dredge.dt)
global_mod_SD_temp_gls <- gls(annual_dissimilarity_value ~
survey_unit*yearly_mean_bypoint_SD.scaledacrossall + #temp and survey unit (possible interaction)
survey_unit*summed_tonnes_scaled_byreg + #fishing effort and survey unit (possible interaction)
area_km.scaledacrossall + #area
latitude_annual_range.scaledacrossall + #latitude range
latitude_annual_avg.scaledacrossall + #latitude avg
depth_annual_range.scaledacrossall + #depth range
depth_annual_avg.scaledacrossall + #depth avg
spp_count_annual.scaledacrossall + #spp #
haul_id_count_annual.scaledacrossall +
julian_scaled,
correlation = corAR1(form=~year | survey_unit),
data = dissimilarity_covariates_dredge.dt)
View(AICc(global_mod_mean_temp_lm, global_mod_max_temp_lm, global_mod_min_temp_lm, global_mod_seas_temp_lm, global_mod_SD_temp_lm,
global_mod_mean_temp_gls, global_mod_max_temp_gls, global_mod_min_temp_gls, global_mod_seas_temp_gls, global_mod_SD_temp_gls))
#build data table to report AICc
global_mod_temp_table <- data.table(
`Temporal autocorrelation` = c(
c(rep(F,5),rep(T,5))
),
`Temperature variable` = rep(c(
"Average mean SBT",
"Average maximum SBT",
"Average minimum SBT",
"Average SBT seasonality",
"SBT SD"),2),
deltaAICc = signif(min(AICc(global_mod_mean_temp_lm, global_mod_max_temp_lm, global_mod_min_temp_lm, global_mod_seas_temp_lm, global_mod_SD_temp_lm,
global_mod_mean_temp_gls, global_mod_max_temp_gls, global_mod_min_temp_gls, global_mod_seas_temp_gls, global_mod_SD_temp_gls)[,2])-AICc(global_mod_mean_temp_lm, global_mod_max_temp_lm, global_mod_min_temp_lm, global_mod_seas_temp_lm, global_mod_SD_temp_lm,
global_mod_mean_temp_gls, global_mod_max_temp_gls, global_mod_min_temp_gls, global_mod_seas_temp_gls, global_mod_SD_temp_gls)[,2],2))
#order by aicc
setorder(global_mod_temp_table,cols = -"deltaAICc")
global_mod_temp_table[,Rank := seq(1,10,by = 1)]
global_mod_sbt_table <- global_mod_temp_table[,.(Rank,`Temporal autocorrelation`,`Temperature variable`, deltaAICc)]
fwrite(global_mod_sbt_table, here::here("output","global_mod_sbt_table.csv"))
Best performing global model includes minimum temperature (centered
and scaled) (Still the case as of May 6, 2024)
Now, look at different combinations of all predictors (min temp)
using dredge
Global model: global_mod_min_temp
options(na.action = "na.fail") # prevent fitting sub-models to different datasets
dd <- dredge(global_mod_min_temp)
Fixed term is "(Intercept)"
dd.dt <- data.table(dd)
View(dd)
#only models less than 4 delta AICc (2 models)
dd.dt.2 <- dd.dt[delta <= 2,]
colnames(dd.dt.2)
[1] "(Intercept)" "area_km.scaledacrossall"
[3] "depth_annual_avg.scaledacrossall" "depth_annual_range.scaledacrossall"
[5] "haul_id_count_annual.scaledacrossall" "julian_scaled"
[7] "latitude_annual_avg.scaledacrossall" "latitude_annual_range.scaledacrossall"
[9] "spp_count_annual.scaledacrossall" "summed_tonnes_scaled_byreg"
[11] "survey_unit" "yearly_min_bypoint_avg.scaledacrossall"
[13] "summed_tonnes_scaled_byreg:survey_unit" "survey_unit:yearly_min_bypoint_avg.scaledacrossall"
[15] "df" "logLik"
[17] "AICc" "delta"
[19] "weight"
#in this step, we delete coefficient values because we will pull them back in later when we calculate both SE and coefficients (other than interaction, which we keep here)
dd.dt.2.formatted <- dd.dt.2[,Rank := as.numeric(rownames(dd.dt.2))][,.(Rank,
`summed_tonnes_scaled_byreg:survey_unit`,
`survey_unit:yearly_min_bypoint_avg.scaledacrossall`,
delta,
weight, survey_unit
)]
#add r-squared values
# Iterate through the best models and extract R-squared values
r_squared_values <-list()
for (i in 1:nrow(dd.dt.2.formatted)) {
summary_data <- summary(get.models(dd, subset = i)[[1]])
r_squared <- signif(summary_data$r.squared,2)
r_squared_values <- unlist(c(r_squared_values,r_squared))
}
dd.dt.2.formatted[,"R squared" := r_squared_values]
#empty data table
model_coef_se_fill <- data.table(Rank = as.numeric(), coef_name = as.character(),coef = as.numeric(), se = as.numeric())
for (i in 1:nrow(dd.dt.2.formatted)){
model_coef_se_single <- data.table(unlist(coefTable(dd,full = T)[[i]]))
model_coef_se_single[,coef_names := rownames(unlist(coefTable(dd,full = T)[[i]]))]
model_coef_se_single[,Rank := i]
colnames(model_coef_se_single) <- c("coef","se","df","coef_name","Rank")
#reduce to columns we need
model_coef_se_single <- model_coef_se_single[,.(Rank, coef_name, coef, se)]
model_coef_se_fill <- rbind(model_coef_se_fill,model_coef_se_single)
}
#format to merge with model rankings and averaged model
model_coef_se_fill[,coef_se := paste0(round(coef,3)," ± ",round(se,3))]
#delete extra columns
model_coef_se_fill <- model_coef_se_fill[,.(Rank,coef_name,coef_se)]
#long to wide
model_coef_se_fill.w <- dcast(model_coef_se_fill, formula = Rank ~ coef_name, value.var = c("coef_se"))
#merge model_coef_se_fill with dd.dt.2.formatted
model_coef_se_AIC <- dd.dt.2.formatted[model_coef_se_fill.w, on = "Rank"]
#model average all models with delta < 4 (50 models)
model_avg_delta4 <-model.avg(dd, subset = delta < 4, fit = T) #NB: The āsubsetā (or āconditionalā) average only averages over the models where the parameter appears. An alternative, the āfullā average assumes that a variable is included in every model, but in some models the corresponding coefficient (and its respective variance) is set to zero. Unlike the āsubset averageā, it does not have a tendency of biasing the value away from zero. The āfullā average is a type of shrinkage estimator, and for variables with a weak relationship to the response it is smaller than āsubsetā estimators., fit = T fits the component models again
model_avg_values <- as.data.table(coefTable(model_avg_delta4,fill = T)) # with SE
coef_names <- names(coef(model.avg(dd, subset = delta < 4)))
model_avg_values[,coef_name:=coef_names][,coef:=Estimate][,Estimate:=NULL][,df:=NULL][,se:= `Std. Error`][,`Std. Error` := NULL]
#new column with coef and SE
model_avg_values[,coef_se := paste0(round(coef,3)," ± ",round(se,3))]
#long to wide for model avg
model_avg.wide <- dcast(model_avg_values, formula = . ~ coef_name, value.var = c("coef_se"))
#add rank of "model avg" to table
model_avg.wide[,Rank := "Model avg"]
best_model_sbt_jaccard_table_formatted <- rbind(model_coef_se_AIC, model_avg.wide, fill = T)
#get rid of interaction coefficients
best_model_sbt_jaccard_table_formatted.r <- best_model_sbt_jaccard_table_formatted[,.(Rank,`(Intercept)`,area_km.scaledacrossall,
depth_annual_avg.scaledacrossall,
depth_annual_range.scaledacrossall,
haul_id_count_annual.scaledacrossall,
julian_scaled,
latitude_annual_avg.scaledacrossall,
latitude_annual_range.scaledacrossall,
spp_count_annual.scaledacrossall,
summed_tonnes_scaled_byreg,
survey_unit,
yearly_min_bypoint_avg.scaledacrossall,
`summed_tonnes_scaled_byreg:survey_unit`,
`survey_unit:yearly_min_bypoint_avg.scaledacrossall`,
`R squared`,
delta,
weight
)]
#round to 2 significant figures
#names of numeric columns
numeric_cols <- names(best_model_sbt_jaccard_table_formatted.r)[sapply(best_model_sbt_jaccard_table_formatted.r, is.numeric)]
# Apply signif() only to numeric columns
best_model_sbt_jaccard_table_formatted.r[, (numeric_cols) := lapply(.SD, function(x) if (is.numeric(x)) signif(x, digits = 2) else x), .SDcols = numeric_cols]
#change column names, in caption note that all variables are centered and scaled
colnames(best_model_sbt_jaccard_table_formatted.r) <- c(
"Rank",
"Intercept",
"Area", #scaled across all
"Average depth",
"Depth range",
"Number of tows",
"Average Julian day",
"Average latitude",
"Latitude range",
"Species count",
"Relative catch", #scaled within region
"Survey",
"Average minimum temperature",
"Survey * relative catch",
"Survey * avg min temperature",
"R squared",
paste0("\u0394"," AICc"),
paste0("\u03C9"))
#save as csv
fwrite(best_model_sbt_jaccard_table_formatted.r,here::here("output","best_model_sbt_jaccard_table_formatted.csv"))
Take aways Dissimilarity increases with increasing avg # tows
Dissimilarity decreases with increasing avg latitude Dissimilarity
decreases with increasing Julian day of sampling Dissimilarity increases
with increasing latitude range Dissimilarity increases with increasing
fishing effort Dissimilarity decreases with increasing depth range
Dissimilarity increases with increasing average depth Dissimilarity
increases with increasing area Dissimilarity decreases with increasing
minimum temperature Dissimilarity increases with increasing # spp
Dissimilarity increases with relative fishing catch
Predict dissimilarity across years using averaged model
(model_avg_delta4)
dissimilarity_covariates_dredge.dt_predictions <- copy(dissimilarity_covariates_dredge.dt)
#allowing temp and fishing to vary (aka no changes)
dissimilarity_covariates_dredge.dt_predictions[,pred_dissim := predict(model_avg_delta4, se.fit = T, full = F)[[1]]][,pred_se := predict(model_avg_delta4, se.fit = T, full = F)[[2]]] #full allows us to switch back to mixed effect models
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#constant temp in regions (aka take mean of temperature values within survey units so they are the same value within each year for a survey)
dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg <- copy(dissimilarity_covariates_dredge.dt)
dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg[,yearly_min_bypoint_avg.scaledacrossall:=mean(yearly_min_bypoint_avg.scaledacrossall),.(survey_unit)]
#constant fishing in regions (aka take mean of fishing values within survey units so they are the same value within each year for a survey)
dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg <- copy(dissimilarity_covariates_dredge.dt)
dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg[,summed_tonnes_scaled_byreg:=mean(summed_tonnes_scaled_byreg),.(survey_unit)]
#and then with consistent temp and fishing in regions (aka take mean of both min temp and fishing)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg <- copy(dissimilarity_covariates_dredge.dt)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg[,summed_tonnes_scaled_byreg:=mean(summed_tonnes_scaled_byreg),.(survey_unit)][,yearly_min_bypoint_avg.scaledacrossall:=mean(yearly_min_bypoint_avg.scaledacrossall),.(survey_unit)]
#allowing temp and fishing to vary within regs (normal)
dissimilarity_covariates_dredge.dt_predictions[,pred_dissim :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions)[[1]]][,pred_se :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions)[[2]]]
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#allowing only fishing to vary within regions (with mean temp)
dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg[,pred_dissim :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg)[[1]]][,pred_se :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg)[[2]]]
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#allowing only temperature to vary within regions (with mean fishing pressure)
dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg[,pred_dissim :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg)[[1]]][,pred_se :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg)[[2]]]
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#and then with consistent temp and fishing across regions (mean of both fishing and temp)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg <- copy(dissimilarity_covariates_dredge.dt)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg[,summed_tonnes_scaled_byreg:=mean(summed_tonnes_scaled_byreg),.(survey_unit)][,yearly_min_bypoint_avg.scaledacrossall:=mean(yearly_min_bypoint_avg.scaledacrossall),.(survey_unit)]
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg[,pred_dissim :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg)[[1]]][,pred_se :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg)[[2]]]
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#and then with consistent temp and fishing across regions (mean of both fishing and temp)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing <- copy(dissimilarity_covariates_dredge.dt)
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing[,summed_tonnes_scaled_byreg:=mean(summed_tonnes_scaled_byreg)][,yearly_min_bypoint_avg.scaledacrossall:=mean(yearly_min_bypoint_avg.scaledacrossall)]
dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing[,pred_dissim :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing)[[1]]][,pred_se :=
predict(model_avg_delta4, se.fit = T, full = F, newdata = dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing)[[2]]]
Warning: argument 'full' ignoredWarning: argument 'full' ignored
#FOR COLOR TO MATCH
#sort color link by survey name season
#alphabetical order
color_link_alpha <- setorder(color_link, survey_unit)
#exclude surveys we don't include
color_link_alpha <- color_link_alpha[survey_unit %in% unique(dissimilarity_covariates_dredge.dt_predictions$survey_unit),]
color_alpha_order <- color_link_alpha[,hex]
label_alpha_order <- color_link_alpha[,Survey_Name_Season]
#maintain temp and fishing
#plot
predicted_values_temp_fishing <- ggplot(dissimilarity_covariates_dredge.dt_predictions) +
geom_point(aes(x = year, y = annual_dissimilarity_value, color = survey_unit)) +
geom_line(aes(x = year, y = pred_dissim, color = survey_unit)) +
geom_ribbon(aes(x = year, ymin = pred_dissim-pred_se, ymax = pred_dissim+pred_se, fill = survey_unit), alpha = 0.3) +
scale_color_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
scale_fill_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
labs(x = "Year",y = "Average annual total\nBray Curtis dissimilarity") +
ylim(0,1.5) +
theme_classic() +
ggtitle("Average model predictions")
#average temp and fishing for each region
predicted_values_temp_fishing_meantempfishinginsurvey <- ggplot(dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg) +
geom_point(aes(x = year, y = annual_dissimilarity_value, color = survey_unit)) +
geom_line(aes(x = year, y = pred_dissim, color = survey_unit)) +
geom_ribbon(aes(x = year, ymin = pred_dissim-pred_se, ymax = pred_dissim+pred_se, fill = survey_unit), alpha = 0.3) +
scale_color_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
scale_fill_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
labs(x = "Year",y = "Average annual total\nBray Curtis dissimilarity") +
ylim(0,1.5) +
theme_classic() +
ggtitle("Average model predictions with mean\nsurvey temperature and fishing pressure")
#average temp and fishing across all regions
predicted_values_temp_fishing_meantempfishing <- ggplot(dissimilarity_covariates_dredge.dt_predictions_consistenttempfishing) +
geom_point(aes(x = year, y = annual_dissimilarity_value, color = survey_unit)) +
geom_line(aes(x = year, y = pred_dissim, color = survey_unit)) +
geom_ribbon(aes(x = year, ymin = pred_dissim-pred_se, ymax = pred_dissim+pred_se, fill = survey_unit), alpha = 0.1) +
scale_color_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
scale_fill_manual(values = color_alpha_order, labels = label_alpha_order, name = "Survey") +
labs(x = "Year",y = "Average annual total\nBray Curtis dissimilarity") +
ylim(0,1.5) +
theme_classic() +
ggtitle("Average model predictions with mean\novereall temperature and fishing pressure")
#merge plots
predicted_values_sbt_jaccard_fishing_merge <- cowplot::plot_grid(predicted_values_temp_fishing,
predicted_values_temp_fishing_meantempfishinginsurvey,
predicted_values_temp_fishing_meantempfishing,
ncol = 1)
Warning: Removed 27 rows containing missing values (`geom_line()`).Warning: no non-missing arguments to max; returning -InfWarning: no non-missing arguments to max; returning -Inf
ggsave(predicted_values_sbt_jaccard_fishing_merge, path = here::here("figures"), filename = "predicted_values_sbt_jaccard_fishing_merge.jpg", height = 30, width = 14)
Take dissimilarity values from random normal distribution for each
year for each region, and then calculate slope (1000 times). Do this
for: - Fishing and temperature vary interannually within surveys -
Temperature is held constant (as mean over time series for a survey),
but fishing varies (allows us to look at relative variance explained) -
Fishing is held constant (as mean over time series for a survey), but
temperature varies (allows us to look at relative variance explained) -
Both fishing and temperature held constant (allows us to see role of
other components of the model)
################################################################################
#full predictions
################################################################################
#table with predicted dissimilarity values and standard error of all predicted dissimilarity values (by year)
table <- dissimilarity_covariates_dredge.dt_predictions[,.(survey_unit, pred_dissim, pred_se, year)]
#0) make datatable to populate
predicted_dissim_trends_rnormruns <- data.table()
#1) NEW PREDICTED VALUES FROM DISTRIBUTION
for (i in 1:1000){
table[,rnorm_pred := rnorm(1, mean = pred_dissim, sd = pred_se),.(year, survey_unit)]
#2) CALCULATE LINEAR MODEL TO EXTRACT SURVEY SPECIFIC TREND VALUES
jaccard_total_predicted_lm_singlerun <- lm(rnorm_pred ~ year*survey_unit,data = table)
model_coefs_reduced_predictions_singlerun <- data.table(summary(jaccard_total_predicted_lm_singlerun)$coefficients)
model_coefs_reduced_predictions_singlerun[,var := rownames(summary(jaccard_total_predicted_lm_singlerun)$coefficients)]
#limit to interactions only (check this if there are any model changes!) row 2 and rows 34:64
model_coefs_reduced_predictions_singlerun <- model_coefs_reduced_predictions_singlerun[c(2,34:64),]
#adjust survey unit name by deleting beginning of string
model_coefs_reduced_predictions_singlerun[,survey_unit := substr(var, 17, str_length(var))][var == "year",survey_unit := "AI"]
#calculate interaction coefficients
AI_estimate <- model_coefs_reduced_predictions_singlerun[1,Estimate]
model_coefs_reduced_predictions_singlerun[1,survey_unit_coefficient := AI_estimate]
model_coefs_reduced_predictions_singlerun[2:32,survey_unit_coefficient := (AI_estimate + Estimate)]
predicted_dissim_trends_rnormruns <- rbind(predicted_dissim_trends_rnormruns, model_coefs_reduced_predictions_singlerun[,.(survey_unit, survey_unit_coefficient)])
print(i)
}
#reduce to mean and standard deviation
predicted_dissim_trends_rnormruns[,mean_dissim_coef:= mean(survey_unit_coefficient),survey_unit][,sd_dissim := sd(survey_unit_coefficient),.(survey_unit)]
predicted_dissim_trends_rnormruns.summary <- unique(predicted_dissim_trends_rnormruns[,.(survey_unit, mean_dissim_coef, sd_dissim)])
predicted_dissim_trends_rnormruns.summary[,pred_type := "full"]
################################################################################
#predictions with temp held constant and fishing still varying from year to year
################################################################################
#table with predicted dissimilarity values and standard error of all predicted dissimilarity values (by year)
table_constanttemp <- dissimilarity_covariates_dredge.dt_predictions_consistenttempinreg[,.(survey_unit, pred_dissim, pred_se, year)]
#0) make datatable to populate
predicted_dissim_trends_rnormruns_constanttemp <- data.table()
#1) NEW PREDICTED VALUES FROM DISTRIBUTION
for (i in 1:1000){
table_constanttemp[,rnorm_pred := rnorm(1, mean = pred_dissim, sd = pred_se),.(year, survey_unit)]
#2) CALCULATE LINEAR MODEL FOR SLOPE VALUES
jaccard_total_predicted_lm_singlerun_constanttemp <- lm(rnorm_pred ~ year*survey_unit,data = table_constanttemp)
model_coefs_reduced_predictions_singlerun_constanttemp <- data.table(summary(jaccard_total_predicted_lm_singlerun_constanttemp)$coefficients)
model_coefs_reduced_predictions_singlerun_constanttemp[,var := rownames(summary(jaccard_total_predicted_lm_singlerun_constanttemp)$coefficients)]
#limit to interactions only (check this if there are any model changes!) row 2 and rows 34:64
model_coefs_reduced_predictions_singlerun_constanttemp <- model_coefs_reduced_predictions_singlerun_constanttemp[c(2,34:64),]
#adjust survey unit name by deleting beginning of string
model_coefs_reduced_predictions_singlerun_constanttemp[,survey_unit := substr(var, 17, str_length(var))][var == "year",survey_unit := "AI"]
#calculate interaction coefficients
AI_estimate <- model_coefs_reduced_predictions_singlerun_constanttemp[1,Estimate]
model_coefs_reduced_predictions_singlerun_constanttemp[1,survey_unit_coefficient := AI_estimate]
model_coefs_reduced_predictions_singlerun_constanttemp[2:32,survey_unit_coefficient := (AI_estimate + Estimate)]
predicted_dissim_trends_rnormruns_constanttemp <- rbind(predicted_dissim_trends_rnormruns_constanttemp, model_coefs_reduced_predictions_singlerun_constanttemp[,.(survey_unit, survey_unit_coefficient)])
print(i)
}
#reduce to mean and standard deviation
predicted_dissim_trends_rnormruns_constanttemp[,mean_dissim_coef:= mean(survey_unit_coefficient),survey_unit][,sd_dissim := sd(survey_unit_coefficient),.(survey_unit)]
predicted_dissim_trends_rnormrunsconstant_temp.summary <- unique(predicted_dissim_trends_rnormruns_constanttemp[,.(survey_unit, mean_dissim_coef, sd_dissim)])
predicted_dissim_trends_rnormrunsconstant_temp.summary[,pred_type := "temp_constant"]
predicted_dissim_trends_rnormruns.summary <- rbind(predicted_dissim_trends_rnormruns.summary, predicted_dissim_trends_rnormrunsconstant_temp.summary)
################################################################################
#predictions with fishing held constant (and temperature varying)
################################################################################
#table with predicted dissimilarity values and standard error of all predicted dissimilarity values (by year)
table_constantfishing <- dissimilarity_covariates_dredge.dt_predictions_consistentfishinginreg[,.(survey_unit, pred_dissim, pred_se, year)]
#0) make datatable to populate
predicted_dissim_trends_rnormruns_constantfishing <- data.table()
#1) NEW PREDICTED VALUES FROM DISTRIBUTION
for (i in 1:1000){
table_constantfishing[,rnorm_pred := rnorm(1, mean = pred_dissim, sd = pred_se),.(year, survey_unit)]
#2) CALCULATE LINEAR MODEL FOR SLOPE VALUES
jaccard_total_predicted_lm_singlerun_constantfishing <- lm(rnorm_pred ~ year*survey_unit,data = table_constantfishing)
model_coefs_reduced_predictions_singlerun_constantfishing <- data.table(summary(jaccard_total_predicted_lm_singlerun_constantfishing)$coefficients)
model_coefs_reduced_predictions_singlerun_constantfishing[,var := rownames(summary(jaccard_total_predicted_lm_singlerun_constantfishing)$coefficients)]
#limit to interactions only (check this if there are any model changes!) row 2 and rows 34:64
model_coefs_reduced_predictions_singlerun_constantfishing <- model_coefs_reduced_predictions_singlerun_constantfishing[c(2,34:64),]
#adjust survey unit name by deleting beginning of string
model_coefs_reduced_predictions_singlerun_constantfishing[,survey_unit := substr(var, 17, str_length(var))][var == "year",survey_unit := "AI"]
#calculate interaction coefficients
AI_estimate <- model_coefs_reduced_predictions_singlerun_constantfishing[1,Estimate]
model_coefs_reduced_predictions_singlerun_constantfishing[1,survey_unit_coefficient := AI_estimate]
model_coefs_reduced_predictions_singlerun_constantfishing[2:32,survey_unit_coefficient := (AI_estimate + Estimate)]
predicted_dissim_trends_rnormruns_constantfishing <- rbind(predicted_dissim_trends_rnormruns_constantfishing, model_coefs_reduced_predictions_singlerun_constantfishing[,.(survey_unit, survey_unit_coefficient)])
print(i)
}
#reduce to mean and standard deviation
predicted_dissim_trends_rnormruns_constantfishing[,mean_dissim_coef:= mean(survey_unit_coefficient),survey_unit][,sd_dissim := sd(survey_unit_coefficient),.(survey_unit)]
predicted_dissim_trends_rnormrunsconstant_fishing.summary <- unique(predicted_dissim_trends_rnormruns_constantfishing[,.(survey_unit, mean_dissim_coef, sd_dissim)])
predicted_dissim_trends_rnormrunsconstant_fishing.summary[,pred_type := "fishing_constant"]
predicted_dissim_trends_rnormruns.summary <- rbind(predicted_dissim_trends_rnormruns.summary, predicted_dissim_trends_rnormrunsconstant_fishing.summary)
################################################################################
#predictions with both fishing and temperature held constant (variability goes to other factors we don't account for)
################################################################################
#table with predicted dissimilarity values and standard error of all predicted dissimilarity values (by year)
table_constanttempfishing <- dissimilarity_covariates_dredge.dt_predictions_consistenttempfishinginreg[,.(survey_unit, pred_dissim, pred_se, year)]
#0) make datatable to populate
predicted_dissim_trends_rnormruns_constanttempfishing <- data.table()
#1) NEW PREDICTED VALUES FROM DISTRIBUTION
for (i in 1:1000){
table_constanttempfishing[,rnorm_pred := rnorm(1, mean = pred_dissim, sd = pred_se),.(year, survey_unit)]
#2) CALCULATE LINEAR MODEL FOR SLOPE VALUES
jaccard_total_predicted_lm_singlerun_constanttempfishing <- lm(rnorm_pred ~ year*survey_unit,data = table_constanttempfishing)
model_coefs_reduced_predictions_singlerun_constanttempfishing <- data.table(summary(jaccard_total_predicted_lm_singlerun_constanttempfishing)$coefficients)
model_coefs_reduced_predictions_singlerun_constanttempfishing[,var := rownames(summary(jaccard_total_predicted_lm_singlerun_constanttempfishing)$coefficients)]
#limit to interactions only (check this if there are any model changes!) row 2 and rows 34:64
model_coefs_reduced_predictions_singlerun_constanttempfishing <- model_coefs_reduced_predictions_singlerun_constanttempfishing[c(2,34:64),]
#adjust survey unit name by deleting beginning of string
model_coefs_reduced_predictions_singlerun_constanttempfishing[,survey_unit := substr(var, 17, str_length(var))][var == "year",survey_unit := "AI"]
#calculate interaction coefficients
AI_estimate <- model_coefs_reduced_predictions_singlerun_constanttempfishing[1,Estimate]
model_coefs_reduced_predictions_singlerun_constanttempfishing[1,survey_unit_coefficient := AI_estimate]
model_coefs_reduced_predictions_singlerun_constanttempfishing[2:32,survey_unit_coefficient := (AI_estimate + Estimate)]
predicted_dissim_trends_rnormruns_constanttempfishing <- rbind(predicted_dissim_trends_rnormruns_constanttempfishing, model_coefs_reduced_predictions_singlerun_constanttempfishing[,.(survey_unit, survey_unit_coefficient)])
print(i)
}
#reduce to mean and standard deviation
predicted_dissim_trends_rnormruns_constanttempfishing[,mean_dissim_coef:= mean(survey_unit_coefficient),survey_unit][,sd_dissim := sd(survey_unit_coefficient),.(survey_unit)]
predicted_dissim_trends_rnormrunsconstant_tempfishing.summary <- unique(predicted_dissim_trends_rnormruns_constanttempfishing[,.(survey_unit, mean_dissim_coef, sd_dissim)])
predicted_dissim_trends_rnormrunsconstant_tempfishing.summary[,pred_type := "fishing_and_temp_constant"]
predicted_dissim_trends_rnormruns.summary <- rbind(predicted_dissim_trends_rnormruns.summary, predicted_dissim_trends_rnormrunsconstant_tempfishing.summary)
Plotting observed vs predicted
jaccard_fishing_temp_model_observed_predicted_dt <- jaccard_total_coefs.r[predicted_dissim_trends_rnormruns.summary, on = "survey_unit"]
jaccard_fishing_temp_model_observed_predicted_dt[,pred_lower := mean_dissim_coef-sd_dissim][,pred_upper := mean_dissim_coef+sd_dissim]
#FULL MODEL, both temperature and fishing are allowed to vary
jaccard_fishing_temp_model_observed_predicted_lm <- lm(survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "full"])
summary(jaccard_fishing_temp_model_observed_predicted_lm) #R^2 0.42
Call:
lm(formula = survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type ==
"full"])
Residuals:
Min 1Q Median 3Q Max
-0.0040158 -0.0004766 -0.0001640 0.0003970 0.0030020
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -2.510e-06 2.463e-04 -0.010 0.992
mean_dissim_coef 1.118e+00 2.494e-01 4.483 9.99e-05 ***
---
Signif. codes: 0 ā***ā 0.001 ā**ā 0.01 ā*ā 0.05 ā.ā 0.1 ā ā 1
Residual standard error: 0.001385 on 30 degrees of freedom
Multiple R-squared: 0.4011, Adjusted R-squared: 0.3812
F-statistic: 20.09 on 1 and 30 DF, p-value: 9.994e-05
(jaccard_fishing_temp_model_observed_predicted <- ggplot(jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "full"]) +
geom_errorbar(aes(x = mean_dissim_coef, ymin = lwr, ymax = upr), color = "lightgrey", linewidth = 0.4) +
geom_errorbarh(aes(y = survey_unit_coefficient, xmin = mean_dissim_coef-sd_dissim, xmax = mean_dissim_coef+sd_dissim), color = "lightgrey", linewidth = 0.4) +
geom_point(aes(y = survey_unit_coefficient, x = mean_dissim_coef)) +
geom_smooth(aes(y = survey_unit_coefficient, x = mean_dissim_coef), color = "darkgrey",linetype = "dotted", method = "lm") +
geom_abline(aes(slope = 1, intercept = 0)) +
lims(x = c(min(jaccard_fishing_temp_model_observed_predicted_dt$pred_lower),max(jaccard_fishing_temp_model_observed_predicted_dt$pred_upper))) +
labs(y = "Observed β-diversity trend",x = "Predicted β-diversity trend\n") +
theme_classic()
)

#fishing constant (fishing constant; temperature varies only)
jaccard_fishing_constant_model_observed_predicted_lm <- lm(survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "fishing_constant"])
summary(jaccard_fishing_constant_model_observed_predicted_lm)
Call:
lm(formula = survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type ==
"fishing_constant"])
Residuals:
Min 1Q Median 3Q Max
-0.0037145 -0.0009269 0.0001445 0.0012234 0.0026883
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -0.0002055 0.0002974 -0.691 0.49495
mean_dissim_coef 1.5387839 0.5107700 3.013 0.00522 **
---
Signif. codes: 0 ā***ā 0.001 ā**ā 0.01 ā*ā 0.05 ā.ā 0.1 ā ā 1
Residual standard error: 0.001568 on 30 degrees of freedom
Multiple R-squared: 0.2323, Adjusted R-squared: 0.2067
F-statistic: 9.076 on 1 and 30 DF, p-value: 0.005221
#Temperature as a predictor, not fishing = R^2 = 0.28 (drop in 12% of variance explained when you lose fishing as predictor)
(jaccard_fishing_constant_model_observed_predicted <- ggplot(jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "fishing_constant"]) +
geom_errorbar(aes(x = mean_dissim_coef, ymin = lwr, ymax = upr), color = "lightgrey", linewidth = 0.4) +
geom_errorbarh(aes(y = survey_unit_coefficient, xmin = mean_dissim_coef-sd_dissim, xmax = mean_dissim_coef+sd_dissim), color = "lightgrey", linewidth = 0.4) +
geom_point(aes(y = survey_unit_coefficient, x = mean_dissim_coef)) +
geom_smooth(aes(y = survey_unit_coefficient, x = mean_dissim_coef), color = "darkgrey",linetype = "dotted", method = "lm") +
geom_abline(aes(slope = 1, intercept = 0)) +
lims(x = c(min(jaccard_fishing_temp_model_observed_predicted_dt$pred_lower),max(jaccard_fishing_temp_model_observed_predicted_dt$pred_upper))) +
labs(y = "Observed β-diversity trend",x = "Predicted β-diversity trend\n(temperature varies fishing constant)") +
theme_classic()
)

#temp constant (fishing only; temperature constant)
jaccard_temperature_constant_model_observed_predicted_lm <- lm(survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "temp_constant"])
summary(jaccard_temperature_constant_model_observed_predicted_lm) #0.18 Drop in 22% of variance explained when you lose temperature as a predictor
Call:
lm(formula = survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type ==
"temp_constant"])
Residuals:
Min 1Q Median 3Q Max
-0.0037086 -0.0007951 -0.0000619 0.0004231 0.0043027
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.0001087 0.0002877 0.378 0.7083
mean_dissim_coef 0.6701402 0.2673702 2.506 0.0178 *
---
Signif. codes: 0 ā***ā 0.001 ā**ā 0.01 ā*ā 0.05 ā.ā 0.1 ā ā 1
Residual standard error: 0.001627 on 30 degrees of freedom
Multiple R-squared: 0.1731, Adjusted R-squared: 0.1456
F-statistic: 6.282 on 1 and 30 DF, p-value: 0.01785
(jaccard_temperature_constant_model_observed_predicted <- ggplot(jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "temp_constant"]) +
geom_errorbar(aes(x = mean_dissim_coef, ymin = lwr, ymax = upr), color = "lightgrey", linewidth = 0.4) +
geom_errorbarh(aes(y = survey_unit_coefficient, xmin = mean_dissim_coef-sd_dissim, xmax = mean_dissim_coef+sd_dissim), color = "lightgrey", linewidth = 0.4) +
geom_point(aes(y = survey_unit_coefficient, x = mean_dissim_coef)) +
geom_smooth(aes(y = survey_unit_coefficient, x = mean_dissim_coef), color = "darkgrey",linetype = "dotted", method = "lm") +
geom_abline(aes(slope = 1, intercept = 0)) +
lims(x = c(min(jaccard_fishing_temp_model_observed_predicted_dt$pred_lower),max(jaccard_fishing_temp_model_observed_predicted_dt$pred_upper))) +
labs(y = "Observed β-diversity trend",x = "Predicted β-diversity trend\n(fishing varies temperature constant)") +
theme_classic()
)

#both temperature and fish held constant
jaccard_fishing_temp_model_observed_predicted_tempfishconstantinsurvey_lm <- lm(survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "fishing_and_temp_constant"])
summary(jaccard_fishing_temp_model_observed_predicted_tempfishconstantinsurvey_lm) #%11
Call:
lm(formula = survey_unit_coefficient ~ mean_dissim_coef, data = jaccard_fishing_temp_model_observed_predicted_dt[pred_type ==
"fishing_and_temp_constant"])
Residuals:
Min 1Q Median 3Q Max
-0.0035992 -0.0007889 -0.0002449 0.0009627 0.0039403
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.051e-05 3.211e-04 -0.033 0.974
mean_dissim_coef 1.166e+00 8.503e-01 1.372 0.180
Residual standard error: 0.001736 on 30 degrees of freedom
Multiple R-squared: 0.05902, Adjusted R-squared: 0.02766
F-statistic: 1.882 on 1 and 30 DF, p-value: 0.1803
(jaccard_fishing_temp_model_observed_predicted_tempfishconstantinsurvey <- ggplot(jaccard_fishing_temp_model_observed_predicted_dt[pred_type == "fishing_and_temp_constant"]) +
geom_errorbar(aes(x = mean_dissim_coef, ymin = lwr, ymax = upr), color = "lightgrey", linewidth = 0.4) +
geom_errorbarh(aes(y = survey_unit_coefficient, xmin = mean_dissim_coef-sd_dissim, xmax = mean_dissim_coef+sd_dissim), color = "lightgrey", linewidth = 0.4) +
geom_point(aes(y = survey_unit_coefficient, x = mean_dissim_coef)) +
geom_smooth(aes(y = survey_unit_coefficient, x = mean_dissim_coef), color = "darkgrey",linetype = "dotted", method = "lm")+
geom_abline(aes(slope = 1, intercept = 0)) +
lims(x = c(min(jaccard_fishing_temp_model_observed_predicted_dt$pred_lower),max(jaccard_fishing_temp_model_observed_predicted_dt$pred_upper))) +
labs(y = "Observed β-diversity trend",x = "Predicted β-diversity trend\n(fishing and temperature constant)") +
theme_classic()
)
#merge
jaccard_fishing_sbt_model_observed_predicted_merge <- plot_grid(jaccard_fishing_temp_model_observed_predicted + theme(plot.margin = unit(c(0.1,0.3,0.1,0.1),"cm")),
jaccard_fishing_constant_model_observed_predicted + theme(plot.margin = unit(c(0.1,0.3,0.1,0.1),"cm")),
jaccard_temperature_constant_model_observed_predicted + theme(plot.margin = unit(c(0.1,0.3,0.1,0.1),"cm")),
jaccard_fishing_temp_model_observed_predicted_tempfishconstantinsurvey + theme(plot.margin = unit(c(0.1,0.3,0.1,0.1),"cm")), ncol = 2, labels = c("a.","b.","c.","d."))
`geom_smooth()` using formula = 'y ~ x'`geom_smooth()` using formula = 'y ~ x'`geom_smooth()` using formula = 'y ~ x'`geom_smooth()` using formula = 'y ~ x'
ggsave(jaccard_fishing_sbt_model_observed_predicted_merge, path = here::here("figures"),filename = "jaccard_fishing_sbt_model_observed_predicted_merge.jpg", height =6, width = 8)

NA
NA
Letās visualize model coefficients with temperature and fishing
(similar to figure 2) model_avg_values
model_avg_values
interaction_avg_model_coef <- model_avg_values[c(5,37:99),.(coef_name, coef, se)]
#insert AI
interaction_avg_model_coef[1:2,survey_unit := "AI"][1:2,coef_true := coef][1:2,predictor := c("Relative fishing catch","Minimum temperature")]
#Other summed_tonnes_scaled_byreg
interaction_avg_model_coef[3:33,survey_unit := substr(coef_name, 39, str_length(coef_name))][3:33,coef_true := interaction_avg_model_coef[1,coef_true]+coef][3:33,predictor := "Relative fishing catch"]
#Other yearly_min_bypoint_avg.scaledacrossall
interaction_avg_model_coef[34:64,survey_unit := substr(coef_name, str_length("survey_unit")+1, str_length(coef_name)-str_length("yearly_min_bypoint_avg.scaledacrossall")-1)][34:64,coef_true := interaction_avg_model_coef[2,coef_true]+coef][34:64,predictor := "Minimum temperature"]
#reorder temperature and fishing
interaction_avg_model_coef[,predictor := factor(predictor, levels = c("Minimum temperature","Relative fishing catch"))]
#link for full survey name
interaction_avg_model_coef <- color_link[interaction_avg_model_coef, on = "survey_unit"]
#reorder by survey_unit
interaction_avg_model_coef[,Survey_Name_Season := reorder(Survey_Name_Season, survey_unit, decreasing = TRUE)]
Warning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NAWarning: argument is not numeric or logical: returning NA
#mark significance
interaction_avg_model_coef[,Significant := ifelse((coef_true-se > 0 & coef_true+se > 0) | (coef_true-se < 0 & coef_true+se < 0),T,F)]
#Plot both
sbt_fishing_avg_model_coef <- ggplot() +
geom_hline(yintercept = 0, linetype = "dotted") +
geom_point(data = interaction_avg_model_coef, aes(x = Survey_Name_Season, y = coef_true, color = Significant)) +
geom_errorbar(data = interaction_avg_model_coef, aes(x = Survey_Name_Season, ymin = coef_true-se, ymax = coef_true+se, color = Significant), width = 0) +
scale_color_manual(values = c("darkgrey","black")) +
facet_wrap(~predictor, scales = "free_x") +
scale_x_discrete(limits = rev) +
labs(y = "Coefficient", x = "") +
coord_flip() +
theme_classic()
Plot all other coefficients in averaged model
model_avg_values.nonfishortemp <- model_avg_values[c(2,3,4,100:104),]
#mark significance
model_avg_values.nonfishortemp[,Significant := ifelse((coef-se > 0 & coef+se > 0) | (coef-se < 0 & coef+se < 0),T,F)]
#more helpful names for variables
model_avg_values.nonfishortemp[,Variable := c("Area","Julian day","Species count","Number of tows","Latitude range","Depth","Latitude","Depth range")]
#make factor with order
model_avg_values.nonfishortemp[,Variable := factor(Variable, levels = c("Area","Julian day","Species count","Number of tows","Depth","Depth range","Latitude","Latitude range"))]
#plot
all_avg_model_coef <- ggplot() +
geom_point(data = model_avg_values.nonfishortemp, aes(x = Variable, y = coef, color = Significant)) +
geom_errorbar(data = model_avg_values.nonfishortemp, aes(x = Variable, ymin = coef-se, ymax = coef+se, color = Significant), width = 0) +
scale_color_manual(values = c("darkgrey","black")) +
geom_hline(yintercept = 0) +
scale_x_discrete(limits = rev) +
labs(y = "Coefficient", x = "\n\n\n") +
coord_flip() +
theme_classic()
#plot
all_but_lat_avg_model_coef <- ggplot() +
geom_point(data = model_avg_values.nonfishortemp[Variable == "Latitude"], aes(x = Variable, y = coef, color = Significant)) +
geom_errorbar(data = model_avg_values.nonfishortemp[Variable == "Latitude"], aes(x = Variable, ymin = coef-se, ymax = coef+se, color = Significant), width = 0) +
scale_color_manual(values = c("darkgrey","black")) +
geom_hline(yintercept = 0) +
scale_x_discrete(limits = rev) +
labs(y = "Coefficient", x = "Model variable") +
coord_flip() +
theme_classic()
#plot
lat_avg_model_coef <- ggplot() +
geom_point(data = model_avg_values.nonfishortemp[Variable != "Latitude"], aes(x = Variable, y = coef, color = Significant)) +
geom_errorbar(data = model_avg_values.nonfishortemp[Variable != "Latitude"], aes(x = Variable, ymin = coef-se, ymax = coef+se, color = Significant), width = 0) +
scale_color_manual(values = c("darkgrey","black")) +
geom_hline(yintercept = 0) +
scale_x_discrete(limits = rev) +
labs(y = "Coefficient", x = "Model variable") +
coord_flip() +
theme_classic()
#merge into single plot
model_coef_summary_sbt_jaccard <- cowplot::plot_grid(sbt_fishing_avg_model_coef+theme(legend.position = "null", axis.title.x = element_blank()),all_avg_model_coef+theme(legend.position = "null"), ncol = 1, labels = c(" a. b."," c."), label_y = 0.99, rel_heights = c(3,1))
ggsave(model_coef_summary_sbt_jaccard, path = here::here("figures"),filename = "model_coef_summary_sbt_jaccard.jpg", height = 6.5, width = 8, unit = "in")
LS0tCnRpdGxlOiAiTW9kZWwgYW5udWFsIGRpc3NpbWlsYXJpdHkgd2l0aCB0ZW1wZXJhdHVyZSwgZmlzaGluZywgYW5kIHN1cnZleSBpZGVudGl0eSIKb3V0cHV0OiBodG1sX25vdGVib29rCmF1dGhvcjogWm/DqyBKLiBLaXRjaGVsCmRhdGU6IE1heSA2LCAyMDI1Ci0tLQoKU2NyaXB0IDggZm9yIEtpdGNoZWwgZXQgYWwuIDIwMjQgaW4gcHJlcCB0YXhvbm9taWMgZGl2ZXJzaXR5IG1hbnVzY3JpcHQuCgoKYGBge3Igc2V0dXB9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShNdU1JbikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkobG1lNCkKbGlicmFyeShzdHJpbmdyKQpgYGAKCiMjI1ByZWRpY3RzIGFubnVhbCBkaXNzaW1pbGFyaXR5IHdpdGggYW5udWFsIGNoYXJhY3RlcmlzdGljcywgdGVtcGVyYXR1cmUgYW5kIGZpc2hpbmcgdmFsdWVzCgpQdWxsIGluCi0gcmVnaW9uIGFyZWFzIChpZiBub3QgYWxyZWFkeSBsb2FkZWQpCi0gcmVnaW9uIGNoYXJhY3RlcmlzdGljcyAoaWYgbm90IGFscmVhZHkgbG9hZGVkKTsgc2F2ZVJEUyhGaXNoR2xvYl9yaWNobmVzc195ZWFyX3N1cnZleSwgZmlsZSA9IGhlcmU6OmhlcmUoIm91dHB1dCIsIkZpc2hHbG9iX3JpY2huZXNzX3llYXJfc3VydmV5LlJkcyIpKQotIGZpc2hpbmcgKGlmIG5vdCBhbHJlYWR5IGxvYWRlZCkKLSB0ZW1wIChpZiBub3QgYWxyZWFkeSBsb2FkZWQpCgoKCmBgYHtyfQojcGh5c2ljYWwgYXJlYSBieSB5ZWFyCnJlZ2lvbl9hcmVhX2J5eWVhciA8LSBmcmVhZChoZXJlOjpoZXJlKCJvdXRwdXQiLCJyZWdpb25fYXJlYV9ieXllYXIuY3N2IikpCgojbWVyZ2VkIGZpc2hpbmcsIHRlbXAsIGRpc3NpbWlsYXJpdGllcwpkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nIDwtIGZyZWFkKGhlcmU6OmhlcmUoIm91dHB1dCIsImRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmcuY3N2IikpCgojY29tYmluZQpkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEgPC0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ1tyZWdpb25fYXJlYV9ieXllYXIsIG9uID0gYygic3VydmV5X3VuaXQiLCJ5ZWFyIildCgojb25seSBqYWNjYXJkIGZvciB0aGVzZSBhbmFseXNlcwpkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZCA8LSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWFbZGlzc2ltaWxhcml0eV9tZXRyaWMgPT0gImphY2NhcmRfZGlzc2ltaWxhcml0eV90b3RhbCIsXQpgYGAKCkFkZCBpbiBhdmVyYWdlIEp1bGlhbiBkYXkKYGBge3J9CiNsb2FkIHVwIGp1bGlhbiBkYXlzCmRhdGVzX3JlZ2lvbnMgPC0gcmVhZFJEUyhoZXJlOjpoZXJlKCJvdXRwdXQiLCJkYXRlc19yZWdpb25zLnJkcyIpKQoKI3NpbXBsaWZ5CmRhdGVzX3JlZ2lvbnMuYW5udWFsIDwtIHVuaXF1ZShkYXRlc19yZWdpb25zWywuKHN1cnZleV91bml0LCB5ZWFyLCBhdmdfanVsaWFuX2FubnVhbCldKQoKI21lcmdlCmRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkIDwtIGRhdGVzX3JlZ2lvbnMuYW5udWFsW2Rpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkLCBvbiA9IGMoInN1cnZleV91bml0IiwieWVhciIpXQpgYGAKCiAKUHVsbCBpbiBwYWxldHRlIGFuZCBuYW1lIGhlbHBlcgpgYGB7cn0Kc291cmNlKGhlcmU6OmhlcmUoImFuYWx5c2lzX2NvZGUiLCJjb2xvcl9saW5rcy5SIikpCmBgYAoKUHVsbCBpbiBvYnNlcnZlZCB0cmVuZCB2YWx1ZXMKYGBge3J9CmphY2NhcmRfdG90YWxfY29lZnMuciA8LSBmcmVhZChoZXJlOjpoZXJlKCJvdXRwdXQiLCJqYWNjYXJkX3RvdGFsX2NvZWZzLnIuY3N2IikpCmBgYAoKUGxvdCBmaXNoaW5nIGFuZCB0ZW1wZXJhdHVyZSB2cy4gdGltZSBmb3IgYWxsIHJlZ2lvbnMKYGBge3J9CiMjIyMjIyNURU1QRVJBVFVSRQoKI3NldCBvcmRlciBieSBzdXJ2ZXkgdW5pdCBmb3IgcGxvdHRpbmcKYWxsX3N1cnZleXMgPC0gbGV2ZWxzKGFzLmZhY3RvcihkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZCRzdXJ2ZXlfdW5pdCkpCnNldG9yZGVyKGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkLCBzdXJ2ZXlfdW5pdCkKCmRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkWyxTdXJ2ZXlfTmFtZV9TZWFzb246PWZhY3RvcihTdXJ2ZXlfTmFtZV9TZWFzb24sIGxldmVscyA9IHVuaXF1ZShkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZCRTdXJ2ZXlfTmFtZV9TZWFzb24pLCBvcmRlcmVkID0gVCldCgooc2J0X3RpbWVfc3VydmV5X2ZhY2V0XzFfMjAgPC0gZ2dwbG90KGRhdGEgPSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFtzdXJ2ZXlfdW5pdCAlaW4lIGFsbF9zdXJ2ZXlzWzE6MjBdICYgeWVhciA+IDE5NzldKSArCiAgbGFicyh5ID0gIk1lYW4gYm90dG9tIHRlbXBlcmF0dXJlICjLmkMpIiwgIHggPSAiWWVhciIpICsKICBnZW9tX3BvaW50KGFlcyh5ID0gYXMubnVtZXJpYyh5ZWFybHlfbWVhbl9ieXBvaW50X2F2ZyksIHggPSB5ZWFyKSwgYWxwaGEgPSAwLjMpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IGFzLm51bWVyaWMoeWVhcmx5X21lYW5fYnlwb2ludF9hdmcpLCB4ID0geWVhciksIG1ldGhvZCA9ICJsbSIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gfiBheGlzVGlja3MoLiwgbG9nID0gRkFMU0UpKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIHNjYWxlcz0gImZyZWUiLCBuY29sID0gNCkpCgpnZ3NhdmUoc2J0X3RpbWVfc3VydmV5X2ZhY2V0XzFfMjAsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gInRlbXBfdGltZV9zdXJ2ZXlfZmFjZXRfMV8yMC5qcGciLCBoZWlnaHQgPSAxMiwgd2lkdGggPTkpCgooc2J0X3RpbWVfc3VydmV5X2ZhY2V0XzIxXzM0IDwtIGdncGxvdChkYXRhID0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1syMTozNF0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHkgPSAiTWVhbiBib3R0b20gdGVtcGVyYXR1cmUgKMuaQykiLCAgeCA9ICJZZWFyIikgKwogIGdlb21fcG9pbnQoYWVzKHkgPSBhcy5udW1lcmljKHllYXJseV9tZWFuX2J5cG9pbnRfYXZnKSwgeCA9IHllYXIpLCBhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKGFlcyh5ID0gYXMubnVtZXJpYyh5ZWFybHlfbWVhbl9ieXBvaW50X2F2ZyksIHggPSB5ZWFyKSwgbWV0aG9kID0gImxtIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSB+IGF4aXNUaWNrcyguLCBsb2cgPSBGQUxTRSkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSkgKwogIGZhY2V0X3dyYXAoflN1cnZleV9OYW1lX1NlYXNvbiwgc2NhbGVzPSAiZnJlZSIsIG5jb2wgPSA0KSkKCmdnc2F2ZShzYnRfdGltZV9zdXJ2ZXlfZmFjZXRfMjFfMzQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gInNidF90aW1lX3N1cnZleV9mYWNldF8yMV8zNC5qcGciLCBoZWlnaHQgPSAxMiwgd2lkdGggPTkpCgojIyMjIyMjRklTSElORwoKZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmQuY2MgPC0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbY29tcGxldGUuY2FzZXMoZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbLHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnXSksXQoKKGZpc2hpbmdfdGltZV9zdXJ2ZXlfZmFjZXRfMV8yMCA8LSBnZ3Bsb3QoZGF0YSA9IGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkLmNjW3N1cnZleV91bml0ICVpbiUgYWxsX3N1cnZleXNbMToyMF0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHkgPSAiUmVsYXRpdmUgZmlzaGluZyBjYXRjaCIsICB4ID0gIlllYXIiKSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnLCB4ID0geWVhciksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZywgeCA9IHllYXIpLCBtZXRob2QgPSAibG0iKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IH4gYXhpc1RpY2tzKC4sIGxvZyA9IEZBTFNFKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBzY2FsZXM9ICJmcmVlIiwgbmNvbCA9IDQpKQoKZ2dzYXZlKGZpc2hpbmdfdGltZV9zdXJ2ZXlfZmFjZXRfMV8yMCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAiZmlzaGluZ190aW1lX3N1cnZleV9mYWNldF8xXzIwLmpwZyIsIGhlaWdodCA9IDEyLCB3aWR0aCA9OSkKCihmaXNoaW5nX3RpbWVfc3VydmV5X2ZhY2V0XzIxXzM0IDwtIGdncGxvdChkYXRhID0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmQuY2Nbc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1tjKDIxOjM0KV0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHkgPSAiUmVsYXRpdmUgZmlzaGluZyBjYXRjaCIsICB4ID0gIlllYXIiKSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnLCB4ID0geWVhciksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZywgeCA9IHllYXIpLCBtZXRob2QgPSAibG0iKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IH4gYXhpc1RpY2tzKC4sIGxvZyA9IEZBTFNFKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBzY2FsZXM9ICJmcmVlIiwgbmNvbCA9IDQpKQoKZ2dzYXZlKGZpc2hpbmdfdGltZV9zdXJ2ZXlfZmFjZXRfMjFfMzQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gImZpc2hpbmdfdGltZV9zdXJ2ZXlfZmFjZXRfMjFfMzQuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKCmBgYAoKUGxvdCBmaXNoaW5nIGFuZCB0ZW1wZXJhdHVyZSB2cy4gZGlzc2ltaWxhcml0eSBmb3IgYWxsIHJlZ2lvbnMKYGBge3J9CiMjIyMjTUVBTiBURU1QCihwcmVkc19zYnRfbWVhbl90ZW1wX3N1cnZleV9mYWNldF8xXzIwIDwtIGdncGxvdChkYXRhID0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1sxOjIwXSAmIHllYXIgPiAxOTc5XSkgKwogIGxhYnMoeCA9ICJNZWFuIGJvdHRvbSB0ZW1wZXJhdHVyZSAoy5pDKSIsICB5ID0gIs6yLWRpdmVyc2l0eSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gYXMubnVtZXJpYyh5ZWFybHlfbWVhbl9ieXBvaW50X2F2ZyksIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSBhcy5udW1lcmljKHllYXJseV9tZWFuX2J5cG9pbnRfYXZnKSwgeSA9IGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlKSwgbWV0aG9kID0gImxtIikgKwogIGZhY2V0X3dyYXAoflN1cnZleV9OYW1lX1NlYXNvbiwgc2NhbGVzPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgdGhlbWVfY2xhc3NpYygpKQoKZ2dzYXZlKHByZWRzX3NidF9tZWFuX3RlbXBfc3VydmV5X2ZhY2V0XzFfMjAsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gInByZWRzX3NidF9tZWFuX3RlbXBfc3VydmV5X2ZhY2V0XzFfMjAuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKKHByZWRzX3NidF9tZWFuX3RlbXBfc3VydmV5X2ZhY2V0XzIxXzM0IDwtIGdncGxvdChkYXRhID0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1syMTozNF0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHggPSAiTWVhbiBib3R0b20gdGVtcGVyYXR1cmUgKMuaQykiLCAgeSA9ICLOsi1kaXZlcnNpdHkiKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGFzLm51bWVyaWMoeWVhcmx5X21lYW5fYnlwb2ludF9hdmcpLCB5ID0gYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUpLCBhbHBoYSA9IDAuMykgKwogIGdlb21fc21vb3RoKGFlcyh4ID0gYXMubnVtZXJpYyh5ZWFybHlfbWVhbl9ieXBvaW50X2F2ZyksIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIG1ldGhvZCA9ICJsbSIpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIHNjYWxlcz0gImZyZWUiLCBuY29sID0gNCkgKwogIHRoZW1lX2NsYXNzaWMoKSkKCmdnc2F2ZShwcmVkc19zYnRfbWVhbl90ZW1wX3N1cnZleV9mYWNldF8yMV8zNCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAicHJlZHNfc2J0X21lYW5fdGVtcF9zdXJ2ZXlfZmFjZXRfMjFfMzQuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKIyMjIyNNSU5JTVVNIFRFTVAKKHByZWRzX3NidF9taW5fdGVtcF9zdXJ2ZXlfZmFjZXRfMV8yMCA8LSBnZ3Bsb3QoZGF0YSA9IGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkW3N1cnZleV91bml0ICVpbiUgYWxsX3N1cnZleXNbMToyMF0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHggPSAiTWluaW11bSBib3R0b20gdGVtcGVyYXR1cmUgKMuaQykiLCAgeSA9ICLOsi1kaXZlcnNpdHkiKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IGFzLm51bWVyaWMoeWVhcmx5X21pbl9ieXBvaW50X2F2ZyksIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSBhcy5udW1lcmljKHllYXJseV9taW5fYnlwb2ludF9hdmcpLCB5ID0gYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUpLCBtZXRob2QgPSAibG0iKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBzY2FsZXM9ICJmcmVlIiwgbmNvbCA9IDQpICsKICB0aGVtZV9jbGFzc2ljKCkpCgpnZ3NhdmUocHJlZHNfc2J0X21pbl90ZW1wX3N1cnZleV9mYWNldF8xXzIwLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJwcmVkc19zYnRfbWluX3RlbXBfc3VydmV5X2ZhY2V0XzFfMjAuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKKHByZWRzX3NidF9taW5fdGVtcF9zdXJ2ZXlfZmFjZXRfMjFfMzQgPC0gZ2dwbG90KGRhdGEgPSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFtzdXJ2ZXlfdW5pdCAlaW4lIGFsbF9zdXJ2ZXlzWzIxOjM0XSAmIHllYXIgPiAxOTc5XSkgKwogIGxhYnMoeCA9ICJNaW5pbXVtIGJvdHRvbSB0ZW1wZXJhdHVyZSAoy5pDKSIsICB5ID0gIs6yLWRpdmVyc2l0eSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gYXMubnVtZXJpYyh5ZWFybHlfbWluX2J5cG9pbnRfYXZnKSwgeSA9IGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlKSwgYWxwaGEgPSAwLjMpICsKICBnZW9tX3Ntb290aChhZXMoeCA9IGFzLm51bWVyaWMoeWVhcmx5X21pbl9ieXBvaW50X2F2ZyksIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIG1ldGhvZCA9ICJsbSIpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIHNjYWxlcz0gImZyZWUiLCBuY29sID0gNCkgKwogIHRoZW1lX2NsYXNzaWMoKSkKCmdnc2F2ZShwcmVkc19zYnRfbWluX3RlbXBfc3VydmV5X2ZhY2V0XzIxXzM0LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJwcmVkc19zYnRfbWluX3RlbXBfc3VydmV5X2ZhY2V0XzIxXzM0LmpwZyIsIGhlaWdodCA9IDEyLCB3aWR0aCA9OSkKCiMjIyMjIyNGSVNISU5HCgpkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZC5jYyA8LSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFtjb21wbGV0ZS5jYXNlcyhkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFssc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWddKSxdCgoocHJlZHNfc2J0X21lYW5fZmlzaGluZ19zdXJ2ZXlfZmFjZXRfMV8yMCA8LSBnZ3Bsb3QoZGF0YSA9IGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkLmNjW3N1cnZleV91bml0ICVpbiUgYWxsX3N1cnZleXNbMToyMF0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHggPSAiUmVsYXRpdmUgZmlzaGluZyBjYXRjaCIsICB5ID0gIs6yLWRpdmVyc2l0eSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcsIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZywgeSA9IGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlKSwgbWV0aG9kID0gImxtIikgKwogIGZhY2V0X3dyYXAoflN1cnZleV9OYW1lX1NlYXNvbiwgc2NhbGVzPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgdGhlbWVfY2xhc3NpYygpKQoKZ2dzYXZlKHByZWRzX3NidF9tZWFuX2Zpc2hpbmdfc3VydmV5X2ZhY2V0XzFfMjAsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksIGZpbGVuYW1lID0gInByZWRzX3NidF9tZWFuX2Zpc2hpbmdfc3VydmV5X2ZhY2V0XzFfMjAuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKKHByZWRzX3NidF9tZWFuX2Zpc2hpbmdfc3VydmV5X2ZhY2V0XzIxXzM0IDwtIGdncGxvdChkYXRhID0gZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmQuY2Nbc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1tjKDIxOjM0KV0gJiB5ZWFyID4gMTk3OV0pICsKICBsYWJzKHggPSAiUmVsYXRpdmUgZmlzaGluZyBjYXRjaCIsICB5ID0gIs6yLWRpdmVyc2l0eSIpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcsIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSksIGFscGhhID0gMC4zKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHggPSBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZywgeSA9IGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlKSwgbWV0aG9kID0gImxtIikgKwogIGZhY2V0X3dyYXAoflN1cnZleV9OYW1lX1NlYXNvbiwgc2NhbGVzPSAiZnJlZSIsIG5jb2wgPSA0KSArCiAgdGhlbWVfY2xhc3NpYygpKQoKZ2dzYXZlKHByZWRzX3NidF9tZWFuX2Zpc2hpbmdfc3VydmV5X2ZhY2V0XzIxXzM0LCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJwcmVkc19zYnRfbWVhbl9maXNoaW5nX3N1cnZleV9mYWNldF8yMV8zNC5qcGciLCBoZWlnaHQgPSAxMiwgd2lkdGggPTkpCgoKYGBgCgojIyNQbG90IG51bWJlciBvZiB0b3dzIHBlciB5ZWFyIHBlciByZWdpb24KYGBge3J9CnRvd3NfeWVhciA8LSB1bmlxdWUoZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmRbLC4oc3VydmV5X3VuaXQsIGhhdWxfaWRfY291bnRfYW5udWFsLCBhcmVhX2ttLCB5ZWFyLCBTdXJ2ZXlfTmFtZV9TZWFzb24pXSkKCm1pbl9oYXVsX2RlbnNpdHkgPC0gbWluKHRvd3NfeWVhciRoYXVsX2lkX2NvdW50X2FubnVhbC90b3dzX3llYXIkYXJlYV9rbSkKbWF4X2hhdWxfZGVuc2l0eSA8LSBtYXgodG93c195ZWFyJGhhdWxfaWRfY291bnRfYW5udWFsL3Rvd3NfeWVhciRhcmVhX2ttKQoKKHRvd19kZW5zaXR5X3N1cnZleV9mYWNldF8xXzIwIDwtIGdncGxvdChkYXRhID0gdG93c195ZWFyW3N1cnZleV91bml0ICVpbiUgYWxsX3N1cnZleXNbMToyMF1dKSArCiAgbGFicyh4ID0gIlllYXIiLCAgeSA9IGV4cHJlc3Npb24oIlRvdyBkZW5zaXR5ICh0b3dzIHBlciBrbSJeMioiKSIpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHllYXIsIHkgPSBoYXVsX2lkX2NvdW50X2FubnVhbC9hcmVhX2ttKSkgKwogIHlsaW0oYyhtaW5faGF1bF9kZW5zaXR5LTAuMDAwMSwgbWF4X2hhdWxfZGVuc2l0eSswLjAwMDEpKSArCiAgZmFjZXRfd3JhcCh+U3VydmV5X05hbWVfU2Vhc29uLCBuY29sID0gNCkgKwogIHRoZW1lX2NsYXNzaWMoKSkKCmdnc2F2ZSh0b3dfZGVuc2l0eV9zdXJ2ZXlfZmFjZXRfMV8yMCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAidG93X2RlbnNpdHlfc3VydmV5X2ZhY2V0XzFfMjAuanBnIiwgaGVpZ2h0ID0gMTIsIHdpZHRoID05KQoKKHRvd19kZW5zaXR5X3N1cnZleV9mYWNldF8yMV8zNCA8LSBnZ3Bsb3QoZGF0YSA9IHRvd3NfeWVhcltzdXJ2ZXlfdW5pdCAlaW4lIGFsbF9zdXJ2ZXlzWzIxOjM0XV0pICsKICBsYWJzKHggPSAiWWVhciIsICB5ID0gZXhwcmVzc2lvbigiVG93IGRlbnNpdHkgKHRvd3MgcGVyIGttIl4yKiIpIikpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geWVhciwgeSA9IGhhdWxfaWRfY291bnRfYW5udWFsL2FyZWFfa20pKSArCiAgeWxpbShjKG1pbl9oYXVsX2RlbnNpdHktMC4wMDAxLCBtYXhfaGF1bF9kZW5zaXR5KzAuMDAwMSkpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIG5jb2wgPSA0KSArCiAgdGhlbWVfY2xhc3NpYygpKQoKZ2dzYXZlKHRvd19kZW5zaXR5X3N1cnZleV9mYWNldF8yMV8zNCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAidG93X2RlbnNpdHlfc3VydmV5X2ZhY2V0XzIxXzM0LmpwZyIsIGhlaWdodCA9IDEyLCB3aWR0aCA9OSkKCiNtaW5pbXVtIGFuZCBtYXhpbXVtIGRpc3NpbWlsYXJpdHkgdmFsdWUKbWluX2Rpc3NpbWlsYXJpdHkgPC0gbWluKGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkJGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlKQptYXhfZGlzc2ltaWxhcml0eSA8LSBtYXgoZGlzc2ltaWxhcml0aWVzX3RlbXBfZmlzaGluZ19hcmVhLmphY2NhcmQkYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUpCgojaG93IGRvZXMgdG93IGRlbnNpdHkgdmFyeSB3aXRoIGRpc3NpbWlsYXJpdHk/CnRvd19kZW5zaXR5X2Rpc3NpbWlsYXJpdHlfMV8yMCA8LSAKICBnZ3Bsb3QoZGF0YSA9IGRpc3NpbWlsYXJpdGllc190ZW1wX2Zpc2hpbmdfYXJlYS5qYWNjYXJkW2Rpc3NpbWlsYXJpdHlfbWV0cmljID09ICJqYWNjYXJkX2Rpc3NpbWlsYXJpdHlfdG90YWwiICYgc3VydmV5X3VuaXQgJWluJSBhbGxfc3VydmV5c1sxOjIwXV0pICsKICBnZW9tX3BvaW50KGFlcyh4ID0gKGhhdWxfaWRfY291bnRfYW5udWFsL2FyZWFfa20pLCB5ID0gYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUsIGNvbG9yID0geWVhciksIHNpemUgPSAyKSArCiAgdmlyaWRpczo6c2NhbGVfY29sb3JfdmlyaWRpcygpICsKICBmYWNldF93cmFwKH5TdXJ2ZXlfTmFtZV9TZWFzb24sIG5jb2wgPSA0KSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbigiVG93IGRlbnNpdHkgKHRvd3MgcGVyIGttIl4yKiIpIiksIHkgPSAizrItZGl2ZXJzaXR5IiwgY29sb3IgPSAiWWVhciIpICsKICAgIHhsaW0oYyhtaW5faGF1bF9kZW5zaXR5LTAuMDAwMSwgbWF4X2hhdWxfZGVuc2l0eSswLjAwMDEpKSArCiAgICB5bGltKGMobWluX2Rpc3NpbWlsYXJpdHktMC4wMSxtYXhfZGlzc2ltaWxhcml0eSswLjAxKSkgKwogIHRoZW1lX2NsYXNzaWMoKQoKZ2dzYXZlKHRvd19kZW5zaXR5X2Rpc3NpbWlsYXJpdHlfMV8yMCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAidG93X2RlbnNpdHlfZGlzc2ltaWxhcml0eV8xXzIwLmpwZyIsIGhlaWdodCA9IDEyLCB3aWR0aCA9OSkKCnRvd19kZW5zaXR5X2Rpc3NpbWlsYXJpdHlfMjFfMzQgPC0gCiAgZ2dwbG90KGRhdGEgPSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFtkaXNzaW1pbGFyaXR5X21ldHJpYyA9PSAiamFjY2FyZF9kaXNzaW1pbGFyaXR5X3RvdGFsIiAmIHN1cnZleV91bml0ICVpbiUgYWxsX3N1cnZleXNbMjE6MzRdXSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSAoaGF1bF9pZF9jb3VudF9hbm51YWwvYXJlYV9rbSksIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSwgY29sb3IgPSB5ZWFyKSwgc2l6ZSA9IDIpICsKICB2aXJpZGlzOjpzY2FsZV9jb2xvcl92aXJpZGlzKCkgKwogIGZhY2V0X3dyYXAoflN1cnZleV9OYW1lX1NlYXNvbiwgbmNvbCA9IDQpICsKICBsYWJzKHggPSBleHByZXNzaW9uKCJUb3cgZGVuc2l0eSAodG93cyBwZXIga20iXjIqIikiKSwgeSA9ICLOsi1kaXZlcnNpdHkiLCBjb2xvciA9ICJZZWFyIikgKwogICAgeGxpbShjKG1pbl9oYXVsX2RlbnNpdHktMC4wMDAxLCBtYXhfaGF1bF9kZW5zaXR5KzAuMDAwMSkpICsKICAgIHlsaW0oYyhtaW5fZGlzc2ltaWxhcml0eS0wLjAxLG1heF9kaXNzaW1pbGFyaXR5KzAuMDEpKSArCiAgdGhlbWVfY2xhc3NpYygpCgpnZ3NhdmUodG93X2RlbnNpdHlfZGlzc2ltaWxhcml0eV8yMV8zNCwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSwgZmlsZW5hbWUgPSAidG93X2RlbnNpdHlfZGlzc2ltaWxhcml0eV8yMV8zNC5qcGciLCBoZWlnaHQgPSAxMiwgd2lkdGggPTkpCmBgYAoKCiMjI1NldCB1cCBkcmVkZ2UgdG8gaWRlbnRpZnkgYmVzdCBwZXJmb3JtaW5nIG1vZGVscwpgYGB7cn0KCm9wdGlvbnMobmEuYWN0aW9uID0gIm5hLmZhaWwiKQoKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCA8LSBkaXNzaW1pbGFyaXRpZXNfdGVtcF9maXNoaW5nX2FyZWEuamFjY2FyZFssLgogICAgICAgICAgICAgICAgICAoeWVhciwgc3VydmV5X3VuaXQsCiAgICAgICAgICAgICAgICAgICAgeWVhcmx5X21lYW5fYnlwb2ludF9hdmcsIHllYXJseV9tYXhfYnlwb2ludF9hdmcsIHllYXJseV9taW5fYnlwb2ludF9hdmcseWVhcmx5X3NlYXNfYnlwb2ludF9hdmcsCiAgICAgICAgICAgICAgICAgICAgeWVhcmx5X21lYW5fYnlwb2ludF9TRCwgeWVhcmx5X21heF9ieXBvaW50X1NELCB5ZWFybHlfbWluX2J5cG9pbnRfU0QseWVhcmx5X3NlYXNfYnlwb2ludF9TRCwKICAgICAgICAgICAgICAgICAgICB5ZWFybHlfbWVhbl9ieXBvaW50X2F2Zy5zLCB5ZWFybHlfbWF4X2J5cG9pbnRfYXZnLnMsIHllYXJseV9taW5fYnlwb2ludF9hdmcucyx5ZWFybHlfc2Vhc19ieXBvaW50X2F2Zy5zLAogICAgICAgICAgICAgICAgICAgIGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlLAogICAgICAgICAgICAgICAgICAgIGhhdWxfaWRfY291bnRfYW5udWFsLAogICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwsIGRlcHRoX2FubnVhbF9hdmcsCiAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLCBsYXRpdHVkZV9hbm51YWxfYXZnLAogICAgICAgICAgICAgICAgICAgIGxhdGl0dWRlX2FubnVhbF9yYW5nZSwgYXJlYV9rbSwgYXZnX2p1bGlhbl9hbm51YWwsIHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnKV0KCiNtZXJnZSBpbiB3aXRoIGNvbG9ycyBmb3IgcGxvdHRpbmcgcHJlZGljdGlvbnMgYnkgc3VydmV5CmRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQgPC0gY29sb3JfbGlua1tkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0LCBvbiA9ICJzdXJ2ZXlfdW5pdCJdCgojSWYgTkEgZm9yIGFueSBjb3ZhcmlhdGUsIGRlbGV0ZSByb3cKVmlldyhkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQojRGVsZXRlZDoKICAjQmVmb3JlIDE5ODAgYW5kIGFmdGVyIDIwMTkKICAjR3VsZiBvZiBTYWludCBMYXVyZW5jZSBTb3V0aCAobm8gZGVwdGggZGF0YSkKICAjTm8gY2xlYXIgU0FVIG1hdGNoIGZvciBSb2NrYWxsIFBsYXRlYXUKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCA8LSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0W2NvbXBsZXRlLmNhc2VzKGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpXQoKCmRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRbLCB5ZWFybHlfbWVhbl9ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGwgOj0gc2NhbGUoeWVhcmx5X21lYW5fYnlwb2ludF9hdmcpXVssIHllYXJseV9tZWFuX2J5cG9pbnRfU0Quc2NhbGVkYWNyb3NzYWxsIDo9IHNjYWxlKHllYXJseV9tZWFuX2J5cG9pbnRfU0QpXVssIHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsIDo9IHNjYWxlKHllYXJseV9taW5fYnlwb2ludF9hdmcpXVssIHllYXJseV9tYXhfYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsIDo9IHNjYWxlKHllYXJseV9tYXhfYnlwb2ludF9hdmcpXVssIHllYXJseV9zZWFzX2J5cG9pbnRfYXZnLnNjYWxlZGFjcm9zc2FsbCA6PSBzY2FsZSh5ZWFybHlfc2Vhc19ieXBvaW50X2F2ZyldWyxoYXVsX2lkX2NvdW50X2FubnVhbC5zY2FsZWRhY3Jvc3NhbGwgOj0gc2NhbGUoaGF1bF9pZF9jb3VudF9hbm51YWwpXVssc3BwX2NvdW50X2FubnVhbC5zY2FsZWRhY3Jvc3NhbGwgOj0gc2NhbGUoc3BwX2NvdW50X2FubnVhbCldWyxkZXB0aF9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCA6PSBzY2FsZShkZXB0aF9hbm51YWxfYXZnKV1bLGRlcHRoX2FubnVhbF9yYW5nZS5zY2FsZWRhY3Jvc3NhbGwgOj0gc2NhbGUoZGVwdGhfYW5udWFsX3JhbmdlKV0gWyxsYXRpdHVkZV9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCA6PSBzY2FsZShsYXRpdHVkZV9hbm51YWxfYXZnKV1bLGxhdGl0dWRlX2FubnVhbF9yYW5nZS5zY2FsZWRhY3Jvc3NhbGwgOj0gc2NhbGUobGF0aXR1ZGVfYW5udWFsX3JhbmdlKV1bLGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsIDo9IHNjYWxlKGFyZWFfa20pXVssanVsaWFuX3NjYWxlZCA6PSBzY2FsZShhdmdfanVsaWFuX2FubnVhbCldCgoKYGBgCgojIyNGdWxsIG1vZGVsCn4gdGVtcCArIHN1cnZleV91bml0ICsgZmlzaGluZyArIGFyZWEgKyBsYXRpdHVkZSByYW5nZSArIGxhdGl0dWRlIGF2ZXJhZ2UgKyBkZXB0aCByYW5nZSArIGRlcHRoIGF2ZXJhZ2UgKyBzcHAgY291bnQgKyAjIG9mIGhhdWxzICsganVsaWFuIGRheSArIEFSIGZvciB5ZWFyCgpGb3IgdGVtcGVyYXR1cmUsIHdlIHdpbGwgbG9vayBhdDoKLW1lYW4gKHNjYWxlZCBhY3Jvc3MgYWxsIHJlZ2lvbnMpCi1tYXggIChzY2FsZWQgYWNyb3NzIGFsbCByZWdpb25zKQotbWluIChzY2FsZWQgYWNyb3NzIGFsbCByZWdpb25zKQotc2VhcyAgKHNjYWxlZCBhY3Jvc3MgYWxsIHJlZ2lvbnMpCi1TRAoKQ29tcGFyaW5nIHRlbXAgdmFyaWFibGVzIEFORCB0aGUgcHJlc2VuY2UvYWJzZW5jZSBvZiBhIHRlbXBvcmFsIGF1dG9jb3JyZWxhdGlvbiB0ZXJtCmBgYHtyIGZpdCBnbG9iYWwgbW9kfQoKZ2xvYmFsX21vZF9tZWFuX3RlbXBfZ2xzIDwtIGdscyhhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9tZWFuX2J5cG9pbnRfYXZnLnNjYWxlZGFjcm9zc2FsbCArICN0ZW1wIGFuZCBzdXJ2ZXkgdW5pdCAocG9zc2libGUgaW50ZXJhY3Rpb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VydmV5X3VuaXQqc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcgKyAjZmlzaGluZyBlZmZvcnQgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmVhX2ttLnNjYWxlZGFjcm9zc2FsbCArICNhcmVhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNsYXRpdHVkZSByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGl0dWRlX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9yYW5nZS5zY2FsZWRhY3Jvc3NhbGwgKyAjZGVwdGggcmFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXB0aF9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCBhdmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHBfY291bnRfYW5udWFsLnNjYWxlZGFjcm9zc2FsbCArICNzcHAgIwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhdWxfaWRfY291bnRfYW5udWFsLnNjYWxlZGFjcm9zc2FsbCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAganVsaWFuX3NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb24gPSBjb3JBUjEoZm9ybT1+eWVhciB8IHN1cnZleV91bml0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCkKCmdsb2JhbF9tb2RfbWVhbl90ZW1wX2xtIDwtIGxtKGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VydmV5X3VuaXQqeWVhcmx5X21lYW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqdWxpYW5fc2NhbGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQoKZ2xvYmFsX21vZF9tYXhfdGVtcF9sbSA8LSBsbShhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9tYXhfYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCgpnbG9iYWxfbW9kX21heF90ZW1wX2dscyA8LWdscyhhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9tYXhfYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMShmb3JtPX55ZWFyIHwgc3VydmV5X3VuaXQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQoKZ2xvYmFsX21vZF9taW5fdGVtcF9sbSA8LSBsbShhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCgpnbG9iYWxfbW9kX21pbl90ZW1wX2dscyA8LWdscyhhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWxhdGlvbiA9IGNvckFSMShmb3JtPX55ZWFyIHwgc3VydmV5X3VuaXQpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQoKZ2xvYmFsX21vZF9zZWFzX3RlbXBfbG0gPC0gbG0oYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCp5ZWFybHlfc2Vhc19ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjdGVtcCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnICsgI2Zpc2hpbmcgZWZmb3J0IGFuZCBzdXJ2ZXkgdW5pdCAocG9zc2libGUgaW50ZXJhY3Rpb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJlYV9rbS5zY2FsZWRhY3Jvc3NhbGwgKyAjYXJlYQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGl0dWRlX2FubnVhbF9yYW5nZS5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgcmFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCArICNsYXRpdHVkZSBhdmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXB0aF9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjZGVwdGggYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BwX2NvdW50X2FubnVhbC5zY2FsZWRhY3Jvc3NhbGwgKyAjc3BwICMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXVsX2lkX2NvdW50X2FubnVhbC5zY2FsZWRhY3Jvc3NhbGwgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCgpnbG9iYWxfbW9kX3NlYXNfdGVtcF9nbHMgPC0gZ2xzKGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlIH4gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VydmV5X3VuaXQqeWVhcmx5X3NlYXNfYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBqdWxpYW5fc2NhbGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlbGF0aW9uID0gY29yQVIxKGZvcm09fnllYXIgfCBzdXJ2ZXlfdW5pdCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCgpnbG9iYWxfbW9kX1NEX3RlbXBfbG0gPC0gbG0oYW5udWFsX2Rpc3NpbWlsYXJpdHlfdmFsdWUgfiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCp5ZWFybHlfbWVhbl9ieXBvaW50X1NELnNjYWxlZGFjcm9zc2FsbCArICN0ZW1wIGFuZCBzdXJ2ZXkgdW5pdCAocG9zc2libGUgaW50ZXJhY3Rpb24pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VydmV5X3VuaXQqc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcgKyAjZmlzaGluZyBlZmZvcnQgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmVhX2ttLnNjYWxlZGFjcm9zc2FsbCArICNhcmVhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNsYXRpdHVkZSByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhdGl0dWRlX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9yYW5nZS5zY2FsZWRhY3Jvc3NhbGwgKyAjZGVwdGggcmFuZ2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXB0aF9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCBhdmcKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHBfY291bnRfYW5udWFsLnNjYWxlZGFjcm9zc2FsbCArICNzcHAgIwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhdWxfaWRfY291bnRfYW5udWFsLnNjYWxlZGFjcm9zc2FsbCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGp1bGlhbl9zY2FsZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCgpnbG9iYWxfbW9kX1NEX3RlbXBfZ2xzIDwtIGdscyhhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSB+IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0KnllYXJseV9tZWFuX2J5cG9pbnRfU0Quc2NhbGVkYWNyb3NzYWxsICsgI3RlbXAgYW5kIHN1cnZleSB1bml0IChwb3NzaWJsZSBpbnRlcmFjdGlvbikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdXJ2ZXlfdW5pdCpzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyArICNmaXNoaW5nIGVmZm9ydCBhbmQgc3VydmV5IHVuaXQgKHBvc3NpYmxlIGludGVyYWN0aW9uKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZWFfa20uc2NhbGVkYWNyb3NzYWxsICsgI2FyZWEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsICsgI2xhdGl0dWRlIHJhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF0aXR1ZGVfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwgKyAjbGF0aXR1ZGUgYXZnCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCArICNkZXB0aCByYW5nZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlcHRoX2FubnVhbF9hdmcuc2NhbGVkYWNyb3NzYWxsICsgI2RlcHRoIGF2ZwogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsgI3NwcCAjCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGF1bF9pZF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsICsKICAgICAgICAgICAgICAgICAgICAgICAgICAganVsaWFuX3NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVsYXRpb24gPSBjb3JBUjEoZm9ybT1+eWVhciB8IHN1cnZleV91bml0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCkKClZpZXcoQUlDYyhnbG9iYWxfbW9kX21lYW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9tYXhfdGVtcF9sbSwgZ2xvYmFsX21vZF9taW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9zZWFzX3RlbXBfbG0sIGdsb2JhbF9tb2RfU0RfdGVtcF9sbSwKICAgICAgICAgIGdsb2JhbF9tb2RfbWVhbl90ZW1wX2dscywgZ2xvYmFsX21vZF9tYXhfdGVtcF9nbHMsIGdsb2JhbF9tb2RfbWluX3RlbXBfZ2xzLCBnbG9iYWxfbW9kX3NlYXNfdGVtcF9nbHMsIGdsb2JhbF9tb2RfU0RfdGVtcF9nbHMpKQoKI2J1aWxkIGRhdGEgdGFibGUgdG8gcmVwb3J0IEFJQ2MKZ2xvYmFsX21vZF90ZW1wX3RhYmxlIDwtIGRhdGEudGFibGUoCiAgYFRlbXBvcmFsIGF1dG9jb3JyZWxhdGlvbmAgPSBjKAogICAgYyhyZXAoRiw1KSxyZXAoVCw1KSkKICApLAogIGBUZW1wZXJhdHVyZSB2YXJpYWJsZWAgPSByZXAoYyggICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAiQXZlcmFnZSBtZWFuIFNCVCIsCiAgICAgICAgICAgICAgIkF2ZXJhZ2UgbWF4aW11bSBTQlQiLCAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICJBdmVyYWdlIG1pbmltdW0gU0JUIiwgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAiQXZlcmFnZSBTQlQgc2Vhc29uYWxpdHkiLCAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIlNCVCBTRCIpLDIpLAogIGRlbHRhQUlDYyA9IHNpZ25pZihtaW4oQUlDYyhnbG9iYWxfbW9kX21lYW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9tYXhfdGVtcF9sbSwgZ2xvYmFsX21vZF9taW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9zZWFzX3RlbXBfbG0sIGdsb2JhbF9tb2RfU0RfdGVtcF9sbSwKICAgICAgICAgIGdsb2JhbF9tb2RfbWVhbl90ZW1wX2dscywgZ2xvYmFsX21vZF9tYXhfdGVtcF9nbHMsIGdsb2JhbF9tb2RfbWluX3RlbXBfZ2xzLCBnbG9iYWxfbW9kX3NlYXNfdGVtcF9nbHMsIGdsb2JhbF9tb2RfU0RfdGVtcF9nbHMpWywyXSktQUlDYyhnbG9iYWxfbW9kX21lYW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9tYXhfdGVtcF9sbSwgZ2xvYmFsX21vZF9taW5fdGVtcF9sbSwgZ2xvYmFsX21vZF9zZWFzX3RlbXBfbG0sIGdsb2JhbF9tb2RfU0RfdGVtcF9sbSwKICAgICAgICAgIGdsb2JhbF9tb2RfbWVhbl90ZW1wX2dscywgZ2xvYmFsX21vZF9tYXhfdGVtcF9nbHMsIGdsb2JhbF9tb2RfbWluX3RlbXBfZ2xzLCBnbG9iYWxfbW9kX3NlYXNfdGVtcF9nbHMsIGdsb2JhbF9tb2RfU0RfdGVtcF9nbHMpWywyXSwyKSkKCiNvcmRlciBieSBhaWNjCnNldG9yZGVyKGdsb2JhbF9tb2RfdGVtcF90YWJsZSxjb2xzID0gLSJkZWx0YUFJQ2MiKQoKZ2xvYmFsX21vZF90ZW1wX3RhYmxlWyxSYW5rIDo9IHNlcSgxLDEwLGJ5ID0gMSldCgpnbG9iYWxfbW9kX3NidF90YWJsZSA8LSBnbG9iYWxfbW9kX3RlbXBfdGFibGVbLC4oUmFuayxgVGVtcG9yYWwgYXV0b2NvcnJlbGF0aW9uYCxgVGVtcGVyYXR1cmUgdmFyaWFibGVgLCBkZWx0YUFJQ2MpXQoKZndyaXRlKGdsb2JhbF9tb2Rfc2J0X3RhYmxlLCBoZXJlOjpoZXJlKCJvdXRwdXQiLCJnbG9iYWxfbW9kX3NidF90YWJsZS5jc3YiKSkKCmBgYAoKQmVzdCBwZXJmb3JtaW5nIGdsb2JhbCBtb2RlbCBpbmNsdWRlcyBtaW5pbXVtIHRlbXBlcmF0dXJlIChjZW50ZXJlZCBhbmQgc2NhbGVkKSAoU3RpbGwgdGhlIGNhc2UgYXMgb2YgTWF5IDYsIDIwMjQpCgpOb3csIGxvb2sgYXQgZGlmZmVyZW50IGNvbWJpbmF0aW9ucyBvZiBhbGwgcHJlZGljdG9ycyAobWluIHRlbXApIHVzaW5nIGRyZWRnZQoKR2xvYmFsIG1vZGVsOiBnbG9iYWxfbW9kX21pbl90ZW1wCgpgYGB7cn0Kb3B0aW9ucyhuYS5hY3Rpb24gPSAibmEuZmFpbCIpICMgIHByZXZlbnQgZml0dGluZyBzdWItbW9kZWxzIHRvIGRpZmZlcmVudCBkYXRhc2V0cwpkZCA8LSBkcmVkZ2UoZ2xvYmFsX21vZF9taW5fdGVtcCkKZGQuZHQgPC0gZGF0YS50YWJsZShkZCkKVmlldyhkZCkKCiNvbmx5IG1vZGVscyBsZXNzIHRoYW4gNCBkZWx0YSBBSUNjICgyIG1vZGVscykKZGQuZHQuMiA8LSBkZC5kdFtkZWx0YSA8PSAyLF0KCmNvbG5hbWVzKGRkLmR0LjIpCgojaW4gdGhpcyBzdGVwLCB3ZSBkZWxldGUgY29lZmZpY2llbnQgdmFsdWVzIGJlY2F1c2Ugd2Ugd2lsbCBwdWxsIHRoZW0gYmFjayBpbiBsYXRlciB3aGVuIHdlIGNhbGN1bGF0ZSBib3RoIFNFIGFuZCBjb2VmZmljaWVudHMgKG90aGVyIHRoYW4gaW50ZXJhY3Rpb24sIHdoaWNoIHdlIGtlZXAgaGVyZSkKZGQuZHQuMi5mb3JtYXR0ZWQgPC0gZGQuZHQuMlssUmFuayA6PSBhcy5udW1lcmljKHJvd25hbWVzKGRkLmR0LjIpKV1bLC4oUmFuaywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWc6c3VydmV5X3VuaXRgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBzdXJ2ZXlfdW5pdDp5ZWFybHlfbWluX2J5cG9pbnRfYXZnLnNjYWxlZGFjcm9zc2FsbGAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2VpZ2h0LCBzdXJ2ZXlfdW5pdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICldCgojYWRkIHItc3F1YXJlZCB2YWx1ZXMKIyBJdGVyYXRlIHRocm91Z2ggdGhlIGJlc3QgbW9kZWxzIGFuZCBleHRyYWN0IFItc3F1YXJlZCB2YWx1ZXMKcl9zcXVhcmVkX3ZhbHVlcyA8LWxpc3QoKQpmb3IgKGkgaW4gMTpucm93KGRkLmR0LjIuZm9ybWF0dGVkKSkgewogIHN1bW1hcnlfZGF0YSA8LSBzdW1tYXJ5KGdldC5tb2RlbHMoZGQsIHN1YnNldCA9IGkpW1sxXV0pCiAgcl9zcXVhcmVkIDwtIHNpZ25pZihzdW1tYXJ5X2RhdGEkci5zcXVhcmVkLDIpCiAgcl9zcXVhcmVkX3ZhbHVlcyA8LSB1bmxpc3QoYyhyX3NxdWFyZWRfdmFsdWVzLHJfc3F1YXJlZCkpCn0KCmRkLmR0LjIuZm9ybWF0dGVkWywiUiBzcXVhcmVkIiA6PSByX3NxdWFyZWRfdmFsdWVzXQoKI2VtcHR5IGRhdGEgdGFibGUKCm1vZGVsX2NvZWZfc2VfZmlsbCA8LSBkYXRhLnRhYmxlKFJhbmsgPSBhcy5udW1lcmljKCksIGNvZWZfbmFtZSA9IGFzLmNoYXJhY3RlcigpLGNvZWYgPSBhcy5udW1lcmljKCksIHNlID0gYXMubnVtZXJpYygpKQoKZm9yIChpIGluIDE6bnJvdyhkZC5kdC4yLmZvcm1hdHRlZCkpewogIG1vZGVsX2NvZWZfc2Vfc2luZ2xlIDwtIGRhdGEudGFibGUodW5saXN0KGNvZWZUYWJsZShkZCxmdWxsID0gVClbW2ldXSkpCiAgbW9kZWxfY29lZl9zZV9zaW5nbGVbLGNvZWZfbmFtZXMgOj0gcm93bmFtZXModW5saXN0KGNvZWZUYWJsZShkZCxmdWxsID0gVClbW2ldXSkpXQogIG1vZGVsX2NvZWZfc2Vfc2luZ2xlWyxSYW5rIDo9IGldCiAgCiAgY29sbmFtZXMobW9kZWxfY29lZl9zZV9zaW5nbGUpIDwtIGMoImNvZWYiLCJzZSIsImRmIiwiY29lZl9uYW1lIiwiUmFuayIpCiAgCiAgI3JlZHVjZSB0byBjb2x1bW5zIHdlIG5lZWQKICBtb2RlbF9jb2VmX3NlX3NpbmdsZSA8LSBtb2RlbF9jb2VmX3NlX3NpbmdsZVssLihSYW5rLCBjb2VmX25hbWUsIGNvZWYsIHNlKV0KICAKICBtb2RlbF9jb2VmX3NlX2ZpbGwgPC0gcmJpbmQobW9kZWxfY29lZl9zZV9maWxsLG1vZGVsX2NvZWZfc2Vfc2luZ2xlKQp9CgojZm9ybWF0IHRvIG1lcmdlIHdpdGggbW9kZWwgcmFua2luZ3MgYW5kIGF2ZXJhZ2VkIG1vZGVsCm1vZGVsX2NvZWZfc2VfZmlsbFssY29lZl9zZSA6PSBwYXN0ZTAocm91bmQoY29lZiwzKSwiIMKxICIscm91bmQoc2UsMykpXQoKI2RlbGV0ZSBleHRyYSBjb2x1bW5zCm1vZGVsX2NvZWZfc2VfZmlsbCA8LSBtb2RlbF9jb2VmX3NlX2ZpbGxbLC4oUmFuayxjb2VmX25hbWUsY29lZl9zZSldCgojbG9uZyB0byB3aWRlCm1vZGVsX2NvZWZfc2VfZmlsbC53IDwtIGRjYXN0KG1vZGVsX2NvZWZfc2VfZmlsbCwgZm9ybXVsYSA9IFJhbmsgfiBjb2VmX25hbWUsIHZhbHVlLnZhciA9IGMoImNvZWZfc2UiKSkKCiNtZXJnZSBtb2RlbF9jb2VmX3NlX2ZpbGwgd2l0aCBkZC5kdC4yLmZvcm1hdHRlZAptb2RlbF9jb2VmX3NlX0FJQyA8LSBkZC5kdC4yLmZvcm1hdHRlZFttb2RlbF9jb2VmX3NlX2ZpbGwudywgb24gPSAiUmFuayJdCgojbW9kZWwgYXZlcmFnZSBhbGwgbW9kZWxzIHdpdGggZGVsdGEgPCA0ICg1MCBtb2RlbHMpCm1vZGVsX2F2Z19kZWx0YTQgPC1tb2RlbC5hdmcoZGQsIHN1YnNldCA9IGRlbHRhIDwgNCwgZml0ID0gVCkgI05COiBUaGUg4oCYc3Vic2V04oCZIChvciDigJhjb25kaXRpb25hbOKAmSkgYXZlcmFnZSBvbmx5ICAgYXZlcmFnZXMgb3ZlciB0aGUgbW9kZWxzIHdoZXJlIHRoZSBwYXJhbWV0ZXIgYXBwZWFycy4gQW4gYWx0ZXJuYXRpdmUsIHRoZSDigJhmdWxs4oCZIGF2ZXJhZ2UgYXNzdW1lcyB0aGF0IGEgdmFyaWFibGUgaXMgaW5jbHVkZWQgaW4gZXZlcnkgbW9kZWwsIGJ1dCBpbiBzb21lIG1vZGVscyB0aGUgY29ycmVzcG9uZGluZyBjb2VmZmljaWVudCAoYW5kIGl0cyByZXNwZWN0aXZlIHZhcmlhbmNlKSBpcyBzZXQgdG8gemVyby4gVW5saWtlIHRoZSDigJhzdWJzZXQgYXZlcmFnZeKAmSwgaXQgZG9lcyBub3QgaGF2ZSBhIHRlbmRlbmN5IG9mIGJpYXNpbmcgdGhlIHZhbHVlIGF3YXkgZnJvbSB6ZXJvLiBUaGUg4oCYZnVsbOKAmSBhdmVyYWdlIGlzIGEgdHlwZSBvZiBzaHJpbmthZ2UgZXN0aW1hdG9yLCBhbmQgZm9yIHZhcmlhYmxlcyB3aXRoIGEgd2VhayByZWxhdGlvbnNoaXAgdG8gdGhlIHJlc3BvbnNlIGl0IGlzIHNtYWxsZXIgdGhhbiDigJhzdWJzZXTigJkgZXN0aW1hdG9ycy4sIGZpdCA9IFQgZml0cyB0aGUgY29tcG9uZW50IG1vZGVscyBhZ2FpbgoKbW9kZWxfYXZnX3ZhbHVlcyA8LSBhcy5kYXRhLnRhYmxlKGNvZWZUYWJsZShtb2RlbF9hdmdfZGVsdGE0LGZpbGwgPSBUKSkgIyB3aXRoIFNFCmNvZWZfbmFtZXMgPC0gbmFtZXMoY29lZihtb2RlbC5hdmcoZGQsIHN1YnNldCA9IGRlbHRhIDwgNCkpKQptb2RlbF9hdmdfdmFsdWVzWyxjb2VmX25hbWU6PWNvZWZfbmFtZXNdWyxjb2VmOj1Fc3RpbWF0ZV1bLEVzdGltYXRlOj1OVUxMXVssZGY6PU5VTExdWyxzZTo9IGBTdGQuIEVycm9yYF1bLGBTdGQuIEVycm9yYCA6PSBOVUxMXQoKI25ldyBjb2x1bW4gd2l0aCBjb2VmIGFuZCBTRQptb2RlbF9hdmdfdmFsdWVzWyxjb2VmX3NlIDo9IHBhc3RlMChyb3VuZChjb2VmLDMpLCIgwrEgIixyb3VuZChzZSwzKSldCgojbG9uZyB0byB3aWRlIGZvciBtb2RlbCBhdmcKbW9kZWxfYXZnLndpZGUgPC0gZGNhc3QobW9kZWxfYXZnX3ZhbHVlcywgZm9ybXVsYSA9IC4gfiBjb2VmX25hbWUsIHZhbHVlLnZhciA9IGMoImNvZWZfc2UiKSkKCiNhZGQgcmFuayBvZiAibW9kZWwgYXZnIiB0byB0YWJsZQptb2RlbF9hdmcud2lkZVssUmFuayA6PSAiTW9kZWwgYXZnIl0KCmJlc3RfbW9kZWxfc2J0X2phY2NhcmRfdGFibGVfZm9ybWF0dGVkIDwtIHJiaW5kKG1vZGVsX2NvZWZfc2VfQUlDLCBtb2RlbF9hdmcud2lkZSwgZmlsbCA9IFQpCgojZ2V0IHJpZCBvZiBpbnRlcmFjdGlvbiBjb2VmZmljaWVudHMKYmVzdF9tb2RlbF9zYnRfamFjY2FyZF90YWJsZV9mb3JtYXR0ZWQuciA8LSBiZXN0X21vZGVsX3NidF9qYWNjYXJkX3RhYmxlX2Zvcm1hdHRlZFssLihSYW5rLGAoSW50ZXJjZXB0KWAsYXJlYV9rbS5zY2FsZWRhY3Jvc3NhbGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX2F2Zy5zY2FsZWRhY3Jvc3NhbGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVwdGhfYW5udWFsX3JhbmdlLnNjYWxlZGFjcm9zc2FsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXVsX2lkX2NvdW50X2FubnVhbC5zY2FsZWRhY3Jvc3NhbGwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAganVsaWFuX3NjYWxlZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfYXZnLnNjYWxlZGFjcm9zc2FsbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXRpdHVkZV9hbm51YWxfcmFuZ2Uuc2NhbGVkYWNyb3NzYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcF9jb3VudF9hbm51YWwuc2NhbGVkYWNyb3NzYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleV91bml0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZzpzdXJ2ZXlfdW5pdGAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYHN1cnZleV91bml0OnllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsYCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgUiBzcXVhcmVkYCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWx0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWlnaHQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXQoKI3JvdW5kIHRvIDIgc2lnbmlmaWNhbnQgZmlndXJlcwoKI25hbWVzIG9mIG51bWVyaWMgY29sdW1ucwpudW1lcmljX2NvbHMgPC0gbmFtZXMoYmVzdF9tb2RlbF9zYnRfamFjY2FyZF90YWJsZV9mb3JtYXR0ZWQucilbc2FwcGx5KGJlc3RfbW9kZWxfc2J0X2phY2NhcmRfdGFibGVfZm9ybWF0dGVkLnIsIGlzLm51bWVyaWMpXQoKIyBBcHBseSBzaWduaWYoKSBvbmx5IHRvIG51bWVyaWMgY29sdW1ucwpiZXN0X21vZGVsX3NidF9qYWNjYXJkX3RhYmxlX2Zvcm1hdHRlZC5yWywgKG51bWVyaWNfY29scykgOj0gbGFwcGx5KC5TRCwgZnVuY3Rpb24oeCkgaWYgKGlzLm51bWVyaWMoeCkpIHNpZ25pZih4LCBkaWdpdHMgPSAyKSBlbHNlIHgpLCAuU0Rjb2xzID0gbnVtZXJpY19jb2xzXQoKI2NoYW5nZSBjb2x1bW4gbmFtZXMsIGluIGNhcHRpb24gbm90ZSB0aGF0IGFsbCB2YXJpYWJsZXMgYXJlIGNlbnRlcmVkIGFuZCBzY2FsZWQKY29sbmFtZXMoYmVzdF9tb2RlbF9zYnRfamFjY2FyZF90YWJsZV9mb3JtYXR0ZWQucikgPC0gYygKIlJhbmsiLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKIkludGVyY2VwdCIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoiQXJlYSIsICAgICAgICNzY2FsZWQgYWNyb3NzIGFsbCAgICAgICAgICAgICAgICAgICAgCiJBdmVyYWdlIGRlcHRoIiwgICAgICAgICAgICAgICAgICAKIkRlcHRoIHJhbmdlIiwgICAgICAgICAgICAgICAgCiJOdW1iZXIgb2YgdG93cyIsICAgICAKIkF2ZXJhZ2UgSnVsaWFuIGRheSIsCiJBdmVyYWdlIGxhdGl0dWRlIiwgICAgICAgICAgICAgICAKIkxhdGl0dWRlIHJhbmdlIiwgICAgICAgICAgICAgCiJTcGVjaWVzIGNvdW50IiwgICAgICAgICAgICAgICAgICAKIlJlbGF0aXZlIGNhdGNoIiwgI3NjYWxlZCB3aXRoaW4gcmVnaW9uICAgICAgICAgICAgICAgICAgICAgICAKIlN1cnZleSIsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiJBdmVyYWdlIG1pbmltdW0gdGVtcGVyYXR1cmUiLCAgICAgICAgICAgIAoiU3VydmV5ICogcmVsYXRpdmUgY2F0Y2giLCAgICAgICAgICAgIAoiU3VydmV5ICogYXZnIG1pbiB0ZW1wZXJhdHVyZSIsCiJSIHNxdWFyZWQiLApwYXN0ZTAoIlx1MDM5NCIsIiBBSUNjIiksICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCnBhc3RlMCgiXHUwM0M5IikpCgoKCiNzYXZlIGFzIGNzdgoKZndyaXRlKGJlc3RfbW9kZWxfc2J0X2phY2NhcmRfdGFibGVfZm9ybWF0dGVkLnIsaGVyZTo6aGVyZSgib3V0cHV0IiwiYmVzdF9tb2RlbF9zYnRfamFjY2FyZF90YWJsZV9mb3JtYXR0ZWQuY3N2IikpCmBgYAoKClRha2UgYXdheXMKRGlzc2ltaWxhcml0eSBpbmNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGF2ZyAjIHRvd3MKRGlzc2ltaWxhcml0eSBkZWNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGF2ZyBsYXRpdHVkZQpEaXNzaW1pbGFyaXR5IGRlY3JlYXNlcyB3aXRoIGluY3JlYXNpbmcgSnVsaWFuIGRheSBvZiBzYW1wbGluZwpEaXNzaW1pbGFyaXR5IGluY3JlYXNlcyB3aXRoIGluY3JlYXNpbmcgbGF0aXR1ZGUgcmFuZ2UKRGlzc2ltaWxhcml0eSBpbmNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGZpc2hpbmcgZWZmb3J0CkRpc3NpbWlsYXJpdHkgZGVjcmVhc2VzIHdpdGggaW5jcmVhc2luZyBkZXB0aCByYW5nZQpEaXNzaW1pbGFyaXR5ICBpbmNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGF2ZXJhZ2UgZGVwdGgKRGlzc2ltaWxhcml0eSBpbmNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGFyZWEKRGlzc2ltaWxhcml0eSAgZGVjcmVhc2VzIHdpdGggaW5jcmVhc2luZyBtaW5pbXVtIHRlbXBlcmF0dXJlCkRpc3NpbWlsYXJpdHkgaW5jcmVhc2VzIHdpdGggaW5jcmVhc2luZyAjIHNwcApEaXNzaW1pbGFyaXR5IGluY3JlYXNlcyB3aXRoIHJlbGF0aXZlIGZpc2hpbmcgY2F0Y2gKCgoKUHJlZGljdCBkaXNzaW1pbGFyaXR5IGFjcm9zcyB5ZWFycyB1c2luZyBhdmVyYWdlZCBtb2RlbCAobW9kZWxfYXZnX2RlbHRhNCkKYGBge3J9CmRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnMgPC0gY29weShkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQoKICAjYWxsb3dpbmcgdGVtcCBhbmQgZmlzaGluZyB0byB2YXJ5IChha2Egbm8gY2hhbmdlcykKICBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zWyxwcmVkX2Rpc3NpbSA6PSBwcmVkaWN0KG1vZGVsX2F2Z19kZWx0YTQsIHNlLmZpdCA9IFQsIGZ1bGwgPSBGKVtbMV1dXVsscHJlZF9zZSA6PSBwcmVkaWN0KG1vZGVsX2F2Z19kZWx0YTQsIHNlLmZpdCA9IFQsIGZ1bGwgPSBGKVtbMl1dXSAjZnVsbCBhbGxvd3MgdXMgdG8gc3dpdGNoIGJhY2sgdG8gbWl4ZWQgZWZmZWN0IG1vZGVscwogIAogIAogIAogICNjb25zdGFudCB0ZW1wIGluIHJlZ2lvbnMgKGFrYSB0YWtlIG1lYW4gb2YgdGVtcGVyYXR1cmUgdmFsdWVzIHdpdGhpbiBzdXJ2ZXkgdW5pdHMgc28gdGhleSBhcmUgdGhlIHNhbWUgdmFsdWUgd2l0aGluIGVhY2ggeWVhciBmb3IgYSBzdXJ2ZXkpCiAgZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGlucmVnIDwtIGNvcHkoZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCkKICBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1waW5yZWdbLHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsOj1tZWFuKHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsKSwuKHN1cnZleV91bml0KV0KCiAgI2NvbnN0YW50IGZpc2hpbmcgaW4gcmVnaW9ucyAoYWthIHRha2UgbWVhbiBvZiBmaXNoaW5nIHZhbHVlcyB3aXRoaW4gc3VydmV5IHVuaXRzIHNvIHRoZXkgYXJlIHRoZSBzYW1lIHZhbHVlIHdpdGhpbiBlYWNoIHllYXIgZm9yIGEgc3VydmV5KQogIGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudGZpc2hpbmdpbnJlZyA8LSBjb3B5KGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCiAgZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50ZmlzaGluZ2lucmVnWyxzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZzo9bWVhbihzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZyksLihzdXJ2ZXlfdW5pdCldCgojYW5kIHRoZW4gd2l0aCBjb25zaXN0ZW50IHRlbXAgYW5kIGZpc2hpbmcgaW4gcmVnaW9ucyAoYWthIHRha2UgbWVhbiBvZiBib3RoIG1pbiB0ZW1wIGFuZCBmaXNoaW5nKQpkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1wZmlzaGluZ2lucmVnIDwtIGNvcHkoZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdCkKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGZpc2hpbmdpbnJlZ1ssc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWc6PW1lYW4oc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcpLC4oc3VydmV5X3VuaXQpXVsseWVhcmx5X21pbl9ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGw6PW1lYW4oeWVhcmx5X21pbl9ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGwpLC4oc3VydmV5X3VuaXQpXQoKCiNhbGxvd2luZyB0ZW1wIGFuZCBmaXNoaW5nIHRvIHZhcnkgd2l0aGluIHJlZ3MgKG5vcm1hbCkKICAgIGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNbLHByZWRfZGlzc2ltIDo9IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3QobW9kZWxfYXZnX2RlbHRhNCwgc2UuZml0ID0gVCwgZnVsbCA9IEYsIG5ld2RhdGEgPSAgIGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnMpW1sxXV1dWyxwcmVkX3NlIDo9IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9ICAgZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9ucylbWzJdXV0KICAKI2FsbG93aW5nIG9ubHkgZmlzaGluZyB0byB2YXJ5IHdpdGhpbiByZWdpb25zICh3aXRoIG1lYW4gdGVtcCkKICAKICAgZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGlucmVnWyxwcmVkX2Rpc3NpbSA6PSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBpbnJlZylbWzFdXV1bLHByZWRfc2UgOj0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0KG1vZGVsX2F2Z19kZWx0YTQsIHNlLmZpdCA9IFQsIGZ1bGwgPSBGLCBuZXdkYXRhID0gZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGlucmVnKVtbMl1dXQoKICAKICAKI2FsbG93aW5nIG9ubHkgdGVtcGVyYXR1cmUgdG8gdmFyeSB3aXRoaW4gcmVnaW9ucyAod2l0aCBtZWFuIGZpc2hpbmcgcHJlc3N1cmUpCiAgICAgCiAgIGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudGZpc2hpbmdpbnJlZ1sscHJlZF9kaXNzaW0gOj0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudGZpc2hpbmdpbnJlZylbWzFdXV1bLHByZWRfc2UgOj0gCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0KG1vZGVsX2F2Z19kZWx0YTQsIHNlLmZpdCA9IFQsIGZ1bGwgPSBGLCBuZXdkYXRhID0gZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50ZmlzaGluZ2lucmVnKVtbMl1dXQogICAKI2FuZCB0aGVuIHdpdGggY29uc2lzdGVudCB0ZW1wIGFuZCBmaXNoaW5nIGFjcm9zcyByZWdpb25zIChtZWFuIG9mIGJvdGggZmlzaGluZyBhbmQgdGVtcCkKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGZpc2hpbmdpbnJlZyA8LSBjb3B5KGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHQpCmRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5naW5yZWdbLHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnOj1tZWFuKHN1bW1lZF90b25uZXNfc2NhbGVkX2J5cmVnKSwuKHN1cnZleV91bml0KV1bLHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsOj1tZWFuKHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsKSwuKHN1cnZleV91bml0KV0KCmRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5naW5yZWdbLHByZWRfZGlzc2ltIDo9IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5naW5yZWcpW1sxXV1dWyxwcmVkX3NlIDo9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5naW5yZWcpW1syXV1dCgoKI2FuZCB0aGVuIHdpdGggY29uc2lzdGVudCB0ZW1wIGFuZCBmaXNoaW5nIGFjcm9zcyByZWdpb25zIChtZWFuIG9mIGJvdGggZmlzaGluZyBhbmQgdGVtcCkKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGZpc2hpbmcgPC0gY29weShkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0KQpkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1wZmlzaGluZ1ssc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWc6PW1lYW4oc3VtbWVkX3Rvbm5lc19zY2FsZWRfYnlyZWcpXVsseWVhcmx5X21pbl9ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGw6PW1lYW4oeWVhcmx5X21pbl9ieXBvaW50X2F2Zy5zY2FsZWRhY3Jvc3NhbGwpXQoKZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGZpc2hpbmdbLHByZWRfZGlzc2ltIDo9IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdChtb2RlbF9hdmdfZGVsdGE0LCBzZS5maXQgPSBULCBmdWxsID0gRiwgbmV3ZGF0YSA9IGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5nKVtbMV1dXVsscHJlZF9zZSA6PQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3QobW9kZWxfYXZnX2RlbHRhNCwgc2UuZml0ID0gVCwgZnVsbCA9IEYsIG5ld2RhdGEgPSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1wZmlzaGluZylbWzJdXV0KCiNGT1IgQ09MT1IgVE8gTUFUQ0gKI3NvcnQgY29sb3IgbGluayBieSBzdXJ2ZXkgbmFtZSBzZWFzb24KI2FscGhhYmV0aWNhbCBvcmRlcgpjb2xvcl9saW5rX2FscGhhIDwtIHNldG9yZGVyKGNvbG9yX2xpbmssIHN1cnZleV91bml0KQoKI2V4Y2x1ZGUgc3VydmV5cyB3ZSBkb24ndCBpbmNsdWRlCmNvbG9yX2xpbmtfYWxwaGEgPC0gY29sb3JfbGlua19hbHBoYVtzdXJ2ZXlfdW5pdCAlaW4lIHVuaXF1ZShkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zJHN1cnZleV91bml0KSxdCgpjb2xvcl9hbHBoYV9vcmRlciA8LSBjb2xvcl9saW5rX2FscGhhWyxoZXhdCmxhYmVsX2FscGhhX29yZGVyIDwtIGNvbG9yX2xpbmtfYWxwaGFbLFN1cnZleV9OYW1lX1NlYXNvbl0KICAKCiNtYWludGFpbiB0ZW1wIGFuZCBmaXNoaW5nCiNwbG90CnByZWRpY3RlZF92YWx1ZXNfdGVtcF9maXNoaW5nIDwtIGdncGxvdChkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHllYXIsIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSwgY29sb3IgPSBzdXJ2ZXlfdW5pdCkpICsKICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gcHJlZF9kaXNzaW0sIGNvbG9yID0gc3VydmV5X3VuaXQpKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSB5ZWFyLCB5bWluID0gcHJlZF9kaXNzaW0tcHJlZF9zZSwgeW1heCA9IHByZWRfZGlzc2ltK3ByZWRfc2UsIGZpbGwgPSBzdXJ2ZXlfdW5pdCksIGFscGhhID0gMC4zKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yX2FscGhhX29yZGVyLCBsYWJlbHMgPSBsYWJlbF9hbHBoYV9vcmRlciwgbmFtZSA9ICJTdXJ2ZXkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JfYWxwaGFfb3JkZXIsIGxhYmVscyA9IGxhYmVsX2FscGhhX29yZGVyLCBuYW1lID0gIlN1cnZleSIpICsKICBsYWJzKHggPSAiWWVhciIseSA9ICJBdmVyYWdlIGFubnVhbCB0b3RhbFxuQnJheSBDdXJ0aXMgZGlzc2ltaWxhcml0eSIpICsKICB5bGltKDAsMS41KSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBnZ3RpdGxlKCJBdmVyYWdlIG1vZGVsIHByZWRpY3Rpb25zIikKCiNhdmVyYWdlIHRlbXAgYW5kIGZpc2hpbmcgZm9yIGVhY2ggcmVnaW9uCnByZWRpY3RlZF92YWx1ZXNfdGVtcF9maXNoaW5nX21lYW50ZW1wZmlzaGluZ2luc3VydmV5IDwtIGdncGxvdChkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1wZmlzaGluZ2lucmVnKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IHllYXIsIHkgPSBhbm51YWxfZGlzc2ltaWxhcml0eV92YWx1ZSwgY29sb3IgPSBzdXJ2ZXlfdW5pdCkpICsKICBnZW9tX2xpbmUoYWVzKHggPSB5ZWFyLCB5ID0gcHJlZF9kaXNzaW0sIGNvbG9yID0gc3VydmV5X3VuaXQpKSArCiAgZ2VvbV9yaWJib24oYWVzKHggPSB5ZWFyLCB5bWluID0gcHJlZF9kaXNzaW0tcHJlZF9zZSwgeW1heCA9IHByZWRfZGlzc2ltK3ByZWRfc2UsIGZpbGwgPSBzdXJ2ZXlfdW5pdCksIGFscGhhID0gMC4zKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yX2FscGhhX29yZGVyLCBsYWJlbHMgPSBsYWJlbF9hbHBoYV9vcmRlciwgbmFtZSA9ICJTdXJ2ZXkiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY29sb3JfYWxwaGFfb3JkZXIsIGxhYmVscyA9IGxhYmVsX2FscGhhX29yZGVyLCBuYW1lID0gIlN1cnZleSIpICsKICBsYWJzKHggPSAiWWVhciIseSA9ICJBdmVyYWdlIGFubnVhbCB0b3RhbFxuQnJheSBDdXJ0aXMgZGlzc2ltaWxhcml0eSIpICsKICB5bGltKDAsMS41KSArCiAgdGhlbWVfY2xhc3NpYygpICsKICBnZ3RpdGxlKCJBdmVyYWdlIG1vZGVsIHByZWRpY3Rpb25zIHdpdGggbWVhblxuc3VydmV5IHRlbXBlcmF0dXJlIGFuZCBmaXNoaW5nIHByZXNzdXJlIikKCiNhdmVyYWdlIHRlbXAgYW5kIGZpc2hpbmcgYWNyb3NzIGFsbCByZWdpb25zCnByZWRpY3RlZF92YWx1ZXNfdGVtcF9maXNoaW5nX21lYW50ZW1wZmlzaGluZyA8LSBnZ3Bsb3QoZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50dGVtcGZpc2hpbmcpICsKICBnZW9tX3BvaW50KGFlcyh4ID0geWVhciwgeSA9IGFubnVhbF9kaXNzaW1pbGFyaXR5X3ZhbHVlLCBjb2xvciA9IHN1cnZleV91bml0KSkgKwogIGdlb21fbGluZShhZXMoeCA9IHllYXIsIHkgPSBwcmVkX2Rpc3NpbSwgY29sb3IgPSBzdXJ2ZXlfdW5pdCkpICsKICBnZW9tX3JpYmJvbihhZXMoeCA9IHllYXIsIHltaW4gPSBwcmVkX2Rpc3NpbS1wcmVkX3NlLCB5bWF4ID0gcHJlZF9kaXNzaW0rcHJlZF9zZSwgZmlsbCA9IHN1cnZleV91bml0KSwgYWxwaGEgPSAwLjEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JfYWxwaGFfb3JkZXIsIGxhYmVscyA9IGxhYmVsX2FscGhhX29yZGVyLCBuYW1lID0gIlN1cnZleSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvcl9hbHBoYV9vcmRlciwgbGFiZWxzID0gbGFiZWxfYWxwaGFfb3JkZXIsIG5hbWUgPSAiU3VydmV5IikgKwogIGxhYnMoeCA9ICJZZWFyIix5ID0gIkF2ZXJhZ2UgYW5udWFsIHRvdGFsXG5CcmF5IEN1cnRpcyBkaXNzaW1pbGFyaXR5IikgKwogIHlsaW0oMCwxLjUpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIGdndGl0bGUoIkF2ZXJhZ2UgbW9kZWwgcHJlZGljdGlvbnMgd2l0aCBtZWFuXG5vdmVyZWFsbCB0ZW1wZXJhdHVyZSBhbmQgZmlzaGluZyBwcmVzc3VyZSIpCgojbWVyZ2UgcGxvdHMKcHJlZGljdGVkX3ZhbHVlc19zYnRfamFjY2FyZF9maXNoaW5nX21lcmdlIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChwcmVkaWN0ZWRfdmFsdWVzX3RlbXBfZmlzaGluZywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RlZF92YWx1ZXNfdGVtcF9maXNoaW5nX21lYW50ZW1wZmlzaGluZ2luc3VydmV5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdGVkX3ZhbHVlc190ZW1wX2Zpc2hpbmdfbWVhbnRlbXBmaXNoaW5nLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDEpCgpnZ3NhdmUocHJlZGljdGVkX3ZhbHVlc19zYnRfamFjY2FyZF9maXNoaW5nX21lcmdlLCBwYXRoID0gaGVyZTo6aGVyZSgiZmlndXJlcyIpLCBmaWxlbmFtZSA9ICJwcmVkaWN0ZWRfdmFsdWVzX3NidF9qYWNjYXJkX2Zpc2hpbmdfbWVyZ2UuanBnIiwgaGVpZ2h0ID0gMzAsIHdpZHRoID0gMTQpCmBgYAoKVGFrZSBkaXNzaW1pbGFyaXR5IHZhbHVlcyBmcm9tIHJhbmRvbSBub3JtYWwgZGlzdHJpYnV0aW9uIGZvciBlYWNoIHllYXIgZm9yIGVhY2ggcmVnaW9uLCBhbmQgdGhlbiBjYWxjdWxhdGUgc2xvcGUgKDEwMDAgdGltZXMpLiBEbyB0aGlzIGZvcjoKIC0gRmlzaGluZyBhbmQgdGVtcGVyYXR1cmUgdmFyeSBpbnRlcmFubnVhbGx5IHdpdGhpbiBzdXJ2ZXlzCiAtIFRlbXBlcmF0dXJlIGlzIGhlbGQgY29uc3RhbnQgKGFzIG1lYW4gb3ZlciB0aW1lIHNlcmllcyBmb3IgYSBzdXJ2ZXkpLCBidXQgZmlzaGluZyB2YXJpZXMgKGFsbG93cyB1cyB0byBsb29rIGF0IHJlbGF0aXZlIHZhcmlhbmNlIGV4cGxhaW5lZCkKIC0gRmlzaGluZyBpcyBoZWxkIGNvbnN0YW50IChhcyBtZWFuIG92ZXIgdGltZSBzZXJpZXMgZm9yIGEgc3VydmV5KSwgYnV0IHRlbXBlcmF0dXJlIHZhcmllcyAoYWxsb3dzIHVzIHRvIGxvb2sgYXQgcmVsYXRpdmUgdmFyaWFuY2UgZXhwbGFpbmVkKQogLSBCb3RoIGZpc2hpbmcgYW5kIHRlbXBlcmF0dXJlIGhlbGQgY29uc3RhbnQgKGFsbG93cyB1cyB0byBzZWUgcm9sZSBvZiBvdGhlciBjb21wb25lbnRzIG9mIHRoZSBtb2RlbCkKIApgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI2Z1bGwgcHJlZGljdGlvbnMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI3RhYmxlIHdpdGggcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIGFuZCBzdGFuZGFyZCBlcnJvciBvZiBhbGwgcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIChieSB5ZWFyKQp0YWJsZSA8LSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zWywuKHN1cnZleV91bml0LCBwcmVkX2Rpc3NpbSwgcHJlZF9zZSwgeWVhcildCiMwKSBtYWtlIGRhdGF0YWJsZSB0byBwb3B1bGF0ZQogIHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVucyA8LSBkYXRhLnRhYmxlKCkKIzEpIE5FVyBQUkVESUNURUQgVkFMVUVTIEZST00gRElTVFJJQlVUSU9OCmZvciAoaSBpbiAxOjEwMDApewogIHRhYmxlWyxybm9ybV9wcmVkIDo9IHJub3JtKDEsIG1lYW4gPSBwcmVkX2Rpc3NpbSwgc2QgPSBwcmVkX3NlKSwuKHllYXIsIHN1cnZleV91bml0KV0KIzIpIENBTENVTEFURSBMSU5FQVIgTU9ERUwgVE8gRVhUUkFDVCBTVVJWRVkgU1BFQ0lGSUMgVFJFTkQgVkFMVUVTCiAgamFjY2FyZF90b3RhbF9wcmVkaWN0ZWRfbG1fc2luZ2xlcnVuIDwtIGxtKHJub3JtX3ByZWQgfiB5ZWFyKnN1cnZleV91bml0LGRhdGEgPSB0YWJsZSkKCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW4gPC0gZGF0YS50YWJsZShzdW1tYXJ5KGphY2NhcmRfdG90YWxfcHJlZGljdGVkX2xtX3NpbmdsZXJ1bikkY29lZmZpY2llbnRzKQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuWyx2YXIgOj0gcm93bmFtZXMoc3VtbWFyeShqYWNjYXJkX3RvdGFsX3ByZWRpY3RlZF9sbV9zaW5nbGVydW4pJGNvZWZmaWNpZW50cyldCiAgCiAgI2xpbWl0IHRvIGludGVyYWN0aW9ucyBvbmx5IChjaGVjayB0aGlzIGlmIHRoZXJlIGFyZSBhbnkgbW9kZWwgY2hhbmdlcyEpIHJvdyAyIGFuZCByb3dzIDM0OjY0CiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW4gPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5bYygyLDM0OjY0KSxdCiAgCiAgI2FkanVzdCBzdXJ2ZXkgdW5pdCBuYW1lIGJ5IGRlbGV0aW5nIGJlZ2lubmluZyBvZiBzdHJpbmcKICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1blssc3VydmV5X3VuaXQgOj0gc3Vic3RyKHZhciwgMTcsIHN0cl9sZW5ndGgodmFyKSldW3ZhciA9PSAieWVhciIsc3VydmV5X3VuaXQgOj0gIkFJIl0KICAKICAjY2FsY3VsYXRlIGludGVyYWN0aW9uIGNvZWZmaWNpZW50cwogIEFJX2VzdGltYXRlIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuWzEsRXN0aW1hdGVdCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5bMSxzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCA6PSBBSV9lc3RpbWF0ZV0KICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1blsyOjMyLHN1cnZleV91bml0X2NvZWZmaWNpZW50IDo9IChBSV9lc3RpbWF0ZSArIEVzdGltYXRlKV0KICAKICBwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnMgPC0gcmJpbmQocHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zLCBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1blssLihzdXJ2ZXlfdW5pdCwgc3VydmV5X3VuaXRfY29lZmZpY2llbnQpXSkKICAKICBwcmludChpKQp9CiAgCiNyZWR1Y2UgdG8gbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc1ssbWVhbl9kaXNzaW1fY29lZjo9IG1lYW4oc3VydmV5X3VuaXRfY29lZmZpY2llbnQpLHN1cnZleV91bml0XVssc2RfZGlzc2ltIDo9IHNkKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSwuKHN1cnZleV91bml0KV0KCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVucy5zdW1tYXJ5IDwtIHVuaXF1ZShwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnNbLC4oc3VydmV5X3VuaXQsIG1lYW5fZGlzc2ltX2NvZWYsIHNkX2Rpc3NpbSldKQoKcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zLnN1bW1hcnlbLHByZWRfdHlwZSA6PSAiZnVsbCJdCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojcHJlZGljdGlvbnMgd2l0aCB0ZW1wIGhlbGQgY29uc3RhbnQgYW5kIGZpc2hpbmcgc3RpbGwgdmFyeWluZyBmcm9tIHllYXIgdG8geWVhcgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojdGFibGUgd2l0aCBwcmVkaWN0ZWQgZGlzc2ltaWxhcml0eSB2YWx1ZXMgYW5kIHN0YW5kYXJkIGVycm9yIG9mIGFsbCBwcmVkaWN0ZWQgZGlzc2ltaWxhcml0eSB2YWx1ZXMgKGJ5IHllYXIpCnRhYmxlX2NvbnN0YW50dGVtcCA8LSBkaXNzaW1pbGFyaXR5X2NvdmFyaWF0ZXNfZHJlZGdlLmR0X3ByZWRpY3Rpb25zX2NvbnNpc3RlbnR0ZW1waW5yZWdbLC4oc3VydmV5X3VuaXQsIHByZWRfZGlzc2ltLCBwcmVkX3NlLCB5ZWFyKV0KIzApIG1ha2UgZGF0YXRhYmxlIHRvIHBvcHVsYXRlCiAgcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcCA8LSBkYXRhLnRhYmxlKCkKIzEpIE5FVyBQUkVESUNURUQgVkFMVUVTIEZST00gRElTVFJJQlVUSU9OCmZvciAoaSBpbiAxOjEwMDApewogIHRhYmxlX2NvbnN0YW50dGVtcFsscm5vcm1fcHJlZCA6PSBybm9ybSgxLCBtZWFuID0gcHJlZF9kaXNzaW0sIHNkID0gcHJlZF9zZSksLih5ZWFyLCBzdXJ2ZXlfdW5pdCldCiMyKSBDQUxDVUxBVEUgTElORUFSIE1PREVMIEZPUiBTTE9QRSBWQUxVRVMKICBqYWNjYXJkX3RvdGFsX3ByZWRpY3RlZF9sbV9zaW5nbGVydW5fY29uc3RhbnR0ZW1wIDwtIGxtKHJub3JtX3ByZWQgfiB5ZWFyKnN1cnZleV91bml0LGRhdGEgPSB0YWJsZV9jb25zdGFudHRlbXApCgogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcCA8LSBkYXRhLnRhYmxlKHN1bW1hcnkoamFjY2FyZF90b3RhbF9wcmVkaWN0ZWRfbG1fc2luZ2xlcnVuX2NvbnN0YW50dGVtcCkkY29lZmZpY2llbnRzKQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcFssdmFyIDo9IHJvd25hbWVzKHN1bW1hcnkoamFjY2FyZF90b3RhbF9wcmVkaWN0ZWRfbG1fc2luZ2xlcnVuX2NvbnN0YW50dGVtcCkkY29lZmZpY2llbnRzKV0KICAKICAjbGltaXQgdG8gaW50ZXJhY3Rpb25zIG9ubHkgKGNoZWNrIHRoaXMgaWYgdGhlcmUgYXJlIGFueSBtb2RlbCBjaGFuZ2VzISkgcm93IDIgYW5kIHJvd3MgMzQ6NjQKICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1bl9jb25zdGFudHRlbXAgPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wW2MoMiwzNDo2NCksXQogIAogICNhZGp1c3Qgc3VydmV5IHVuaXQgbmFtZSBieSBkZWxldGluZyBiZWdpbm5pbmcgb2Ygc3RyaW5nCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wWyxzdXJ2ZXlfdW5pdCA6PSBzdWJzdHIodmFyLCAxNywgc3RyX2xlbmd0aCh2YXIpKV1bdmFyID09ICJ5ZWFyIixzdXJ2ZXlfdW5pdCA6PSAiQUkiXQogIAogICNjYWxjdWxhdGUgaW50ZXJhY3Rpb24gY29lZmZpY2llbnRzCiAgQUlfZXN0aW1hdGUgPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wWzEsRXN0aW1hdGVdCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wWzEsc3VydmV5X3VuaXRfY29lZmZpY2llbnQgOj0gQUlfZXN0aW1hdGVdCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wWzI6MzIsc3VydmV5X3VuaXRfY29lZmZpY2llbnQgOj0gKEFJX2VzdGltYXRlICsgRXN0aW1hdGUpXQogIAogIHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudHRlbXAgPC0gcmJpbmQocHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcCwgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wWywuKHN1cnZleV91bml0LCBzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCldKQogIAogIHByaW50KGkpCn0KICAKI3JlZHVjZSB0byBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24KcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcFssbWVhbl9kaXNzaW1fY29lZjo9IG1lYW4oc3VydmV5X3VuaXRfY29lZmZpY2llbnQpLHN1cnZleV91bml0XVssc2RfZGlzc2ltIDo9IHNkKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSwuKHN1cnZleV91bml0KV0KCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc2NvbnN0YW50X3RlbXAuc3VtbWFyeSA8LSB1bmlxdWUocHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcFssLihzdXJ2ZXlfdW5pdCwgbWVhbl9kaXNzaW1fY29lZiwgc2RfZGlzc2ltKV0pCgpwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnNjb25zdGFudF90ZW1wLnN1bW1hcnlbLHByZWRfdHlwZSA6PSAidGVtcF9jb25zdGFudCJdCgpwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnMuc3VtbWFyeSA8LSByYmluZChwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnMuc3VtbWFyeSwgcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zY29uc3RhbnRfdGVtcC5zdW1tYXJ5KQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI3ByZWRpY3Rpb25zIHdpdGggZmlzaGluZyBoZWxkIGNvbnN0YW50IChhbmQgdGVtcGVyYXR1cmUgdmFyeWluZykKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI3RhYmxlIHdpdGggcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIGFuZCBzdGFuZGFyZCBlcnJvciBvZiBhbGwgcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIChieSB5ZWFyKQp0YWJsZV9jb25zdGFudGZpc2hpbmcgPC0gZGlzc2ltaWxhcml0eV9jb3ZhcmlhdGVzX2RyZWRnZS5kdF9wcmVkaWN0aW9uc19jb25zaXN0ZW50ZmlzaGluZ2lucmVnWywuKHN1cnZleV91bml0LCBwcmVkX2Rpc3NpbSwgcHJlZF9zZSwgeWVhcildCiMwKSBtYWtlIGRhdGF0YWJsZSB0byBwb3B1bGF0ZQogIHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudGZpc2hpbmcgPC0gZGF0YS50YWJsZSgpCiMxKSBORVcgUFJFRElDVEVEIFZBTFVFUyBGUk9NIERJU1RSSUJVVElPTgpmb3IgKGkgaW4gMToxMDAwKXsKICB0YWJsZV9jb25zdGFudGZpc2hpbmdbLHJub3JtX3ByZWQgOj0gcm5vcm0oMSwgbWVhbiA9IHByZWRfZGlzc2ltLCBzZCA9IHByZWRfc2UpLC4oeWVhciwgc3VydmV5X3VuaXQpXQojMikgQ0FMQ1VMQVRFIExJTkVBUiBNT0RFTCBGT1IgU0xPUEUgVkFMVUVTCiAgamFjY2FyZF90b3RhbF9wcmVkaWN0ZWRfbG1fc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZyA8LSBsbShybm9ybV9wcmVkIH4geWVhcipzdXJ2ZXlfdW5pdCxkYXRhID0gdGFibGVfY29uc3RhbnRmaXNoaW5nKQoKICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1bl9jb25zdGFudGZpc2hpbmcgPC0gZGF0YS50YWJsZShzdW1tYXJ5KGphY2NhcmRfdG90YWxfcHJlZGljdGVkX2xtX3NpbmdsZXJ1bl9jb25zdGFudGZpc2hpbmcpJGNvZWZmaWNpZW50cykKICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1bl9jb25zdGFudGZpc2hpbmdbLHZhciA6PSByb3duYW1lcyhzdW1tYXJ5KGphY2NhcmRfdG90YWxfcHJlZGljdGVkX2xtX3NpbmdsZXJ1bl9jb25zdGFudGZpc2hpbmcpJGNvZWZmaWNpZW50cyldCiAgCiAgI2xpbWl0IHRvIGludGVyYWN0aW9ucyBvbmx5IChjaGVjayB0aGlzIGlmIHRoZXJlIGFyZSBhbnkgbW9kZWwgY2hhbmdlcyEpIHJvdyAyIGFuZCByb3dzIDM0OjY0CiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnRmaXNoaW5nIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1tjKDIsMzQ6NjQpLF0KICAKICAjYWRqdXN0IHN1cnZleSB1bml0IG5hbWUgYnkgZGVsZXRpbmcgYmVnaW5uaW5nIG9mIHN0cmluZwogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1ssc3VydmV5X3VuaXQgOj0gc3Vic3RyKHZhciwgMTcsIHN0cl9sZW5ndGgodmFyKSldW3ZhciA9PSAieWVhciIsc3VydmV5X3VuaXQgOj0gIkFJIl0KICAKICAjY2FsY3VsYXRlIGludGVyYWN0aW9uIGNvZWZmaWNpZW50cwogIEFJX2VzdGltYXRlIDwtIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1sxLEVzdGltYXRlXQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1sxLHN1cnZleV91bml0X2NvZWZmaWNpZW50IDo9IEFJX2VzdGltYXRlXQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1syOjMyLHN1cnZleV91bml0X2NvZWZmaWNpZW50IDo9IChBSV9lc3RpbWF0ZSArIEVzdGltYXRlKV0KICAKICBwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnNfY29uc3RhbnRmaXNoaW5nIDwtIHJiaW5kKHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudGZpc2hpbmcsIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50ZmlzaGluZ1ssLihzdXJ2ZXlfdW5pdCwgc3VydmV5X3VuaXRfY29lZmZpY2llbnQpXSkKICAKICBwcmludChpKQp9CiAgCiNyZWR1Y2UgdG8gbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudGZpc2hpbmdbLG1lYW5fZGlzc2ltX2NvZWY6PSBtZWFuKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSxzdXJ2ZXlfdW5pdF1bLHNkX2Rpc3NpbSA6PSBzZChzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCksLihzdXJ2ZXlfdW5pdCldCgpwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnNjb25zdGFudF9maXNoaW5nLnN1bW1hcnkgPC0gdW5pcXVlKHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudGZpc2hpbmdbLC4oc3VydmV5X3VuaXQsIG1lYW5fZGlzc2ltX2NvZWYsIHNkX2Rpc3NpbSldKQoKcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zY29uc3RhbnRfZmlzaGluZy5zdW1tYXJ5WyxwcmVkX3R5cGUgOj0gImZpc2hpbmdfY29uc3RhbnQiXQoKcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zLnN1bW1hcnkgPC0gcmJpbmQocHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zLnN1bW1hcnksIHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc2NvbnN0YW50X2Zpc2hpbmcuc3VtbWFyeSkKCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojcHJlZGljdGlvbnMgd2l0aCBib3RoIGZpc2hpbmcgYW5kIHRlbXBlcmF0dXJlIGhlbGQgY29uc3RhbnQgKHZhcmlhYmlsaXR5IGdvZXMgdG8gb3RoZXIgZmFjdG9ycyB3ZSBkb24ndCBhY2NvdW50IGZvcikKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKI3RhYmxlIHdpdGggcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIGFuZCBzdGFuZGFyZCBlcnJvciBvZiBhbGwgcHJlZGljdGVkIGRpc3NpbWlsYXJpdHkgdmFsdWVzIChieSB5ZWFyKQp0YWJsZV9jb25zdGFudHRlbXBmaXNoaW5nIDwtIGRpc3NpbWlsYXJpdHlfY292YXJpYXRlc19kcmVkZ2UuZHRfcHJlZGljdGlvbnNfY29uc2lzdGVudHRlbXBmaXNoaW5naW5yZWdbLC4oc3VydmV5X3VuaXQsIHByZWRfZGlzc2ltLCBwcmVkX3NlLCB5ZWFyKV0KIzApIG1ha2UgZGF0YXRhYmxlIHRvIHBvcHVsYXRlCiAgcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcGZpc2hpbmcgPC0gZGF0YS50YWJsZSgpCiMxKSBORVcgUFJFRElDVEVEIFZBTFVFUyBGUk9NIERJU1RSSUJVVElPTgpmb3IgKGkgaW4gMToxMDAwKXsKICB0YWJsZV9jb25zdGFudHRlbXBmaXNoaW5nWyxybm9ybV9wcmVkIDo9IHJub3JtKDEsIG1lYW4gPSBwcmVkX2Rpc3NpbSwgc2QgPSBwcmVkX3NlKSwuKHllYXIsIHN1cnZleV91bml0KV0KIzIpIENBTENVTEFURSBMSU5FQVIgTU9ERUwgRk9SIFNMT1BFIFZBTFVFUwogIGphY2NhcmRfdG90YWxfcHJlZGljdGVkX2xtX3NpbmdsZXJ1bl9jb25zdGFudHRlbXBmaXNoaW5nIDwtIGxtKHJub3JtX3ByZWQgfiB5ZWFyKnN1cnZleV91bml0LGRhdGEgPSB0YWJsZV9jb25zdGFudHRlbXBmaXNoaW5nKQoKICBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1bl9jb25zdGFudHRlbXBmaXNoaW5nIDwtIGRhdGEudGFibGUoc3VtbWFyeShqYWNjYXJkX3RvdGFsX3ByZWRpY3RlZF9sbV9zaW5nbGVydW5fY29uc3RhbnR0ZW1wZmlzaGluZykkY29lZmZpY2llbnRzKQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcGZpc2hpbmdbLHZhciA6PSByb3duYW1lcyhzdW1tYXJ5KGphY2NhcmRfdG90YWxfcHJlZGljdGVkX2xtX3NpbmdsZXJ1bl9jb25zdGFudHRlbXBmaXNoaW5nKSRjb2VmZmljaWVudHMpXQogIAogICNsaW1pdCB0byBpbnRlcmFjdGlvbnMgb25seSAoY2hlY2sgdGhpcyBpZiB0aGVyZSBhcmUgYW55IG1vZGVsIGNoYW5nZXMhKSByb3cgMiBhbmQgcm93cyAzNDo2NAogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcGZpc2hpbmcgPC0gbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wZmlzaGluZ1tjKDIsMzQ6NjQpLF0KICAKICAjYWRqdXN0IHN1cnZleSB1bml0IG5hbWUgYnkgZGVsZXRpbmcgYmVnaW5uaW5nIG9mIHN0cmluZwogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcGZpc2hpbmdbLHN1cnZleV91bml0IDo9IHN1YnN0cih2YXIsIDE3LCBzdHJfbGVuZ3RoKHZhcikpXVt2YXIgPT0gInllYXIiLHN1cnZleV91bml0IDo9ICJBSSJdCiAgCiAgI2NhbGN1bGF0ZSBpbnRlcmFjdGlvbiBjb2VmZmljaWVudHMKICBBSV9lc3RpbWF0ZSA8LSBtb2RlbF9jb2Vmc19yZWR1Y2VkX3ByZWRpY3Rpb25zX3NpbmdsZXJ1bl9jb25zdGFudHRlbXBmaXNoaW5nWzEsRXN0aW1hdGVdCiAgbW9kZWxfY29lZnNfcmVkdWNlZF9wcmVkaWN0aW9uc19zaW5nbGVydW5fY29uc3RhbnR0ZW1wZmlzaGluZ1sxLHN1cnZleV91bml0X2NvZWZmaWNpZW50IDo9IEFJX2VzdGltYXRlXQogIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcGZpc2hpbmdbMjozMixzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCA6PSAoQUlfZXN0aW1hdGUgKyBFc3RpbWF0ZSldCiAgCiAgcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcGZpc2hpbmcgPC0gcmJpbmQocHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zX2NvbnN0YW50dGVtcGZpc2hpbmcsIG1vZGVsX2NvZWZzX3JlZHVjZWRfcHJlZGljdGlvbnNfc2luZ2xlcnVuX2NvbnN0YW50dGVtcGZpc2hpbmdbLC4oc3VydmV5X3VuaXQsIHN1cnZleV91bml0X2NvZWZmaWNpZW50KV0pCiAgCiAgcHJpbnQoaSkKfQogIAojcmVkdWNlIHRvIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbgpwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnNfY29uc3RhbnR0ZW1wZmlzaGluZ1ssbWVhbl9kaXNzaW1fY29lZjo9IG1lYW4oc3VydmV5X3VuaXRfY29lZmZpY2llbnQpLHN1cnZleV91bml0XVssc2RfZGlzc2ltIDo9IHNkKHN1cnZleV91bml0X2NvZWZmaWNpZW50KSwuKHN1cnZleV91bml0KV0KCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc2NvbnN0YW50X3RlbXBmaXNoaW5nLnN1bW1hcnkgPC0gdW5pcXVlKHByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc19jb25zdGFudHRlbXBmaXNoaW5nWywuKHN1cnZleV91bml0LCBtZWFuX2Rpc3NpbV9jb2VmLCBzZF9kaXNzaW0pXSkKCnByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVuc2NvbnN0YW50X3RlbXBmaXNoaW5nLnN1bW1hcnlbLHByZWRfdHlwZSA6PSAiZmlzaGluZ19hbmRfdGVtcF9jb25zdGFudCJdCgpwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnMuc3VtbWFyeSA8LSByYmluZChwcmVkaWN0ZWRfZGlzc2ltX3RyZW5kc19ybm9ybXJ1bnMuc3VtbWFyeSwgcHJlZGljdGVkX2Rpc3NpbV90cmVuZHNfcm5vcm1ydW5zY29uc3RhbnRfdGVtcGZpc2hpbmcuc3VtbWFyeSkKYGBgCgpQbG90dGluZyBvYnNlcnZlZCB2cyBwcmVkaWN0ZWQKYGBge3J9CgpqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHQgPC0gamFjY2FyZF90b3RhbF9jb2Vmcy5yW3ByZWRpY3RlZF9kaXNzaW1fdHJlbmRzX3Jub3JtcnVucy5zdW1tYXJ5LCBvbiA9ICJzdXJ2ZXlfdW5pdCJdCgpqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHRbLHByZWRfbG93ZXIgOj0gbWVhbl9kaXNzaW1fY29lZi1zZF9kaXNzaW1dWyxwcmVkX3VwcGVyIDo9IG1lYW5fZGlzc2ltX2NvZWYrc2RfZGlzc2ltXQoKI0ZVTEwgTU9ERUwsIGJvdGggdGVtcGVyYXR1cmUgYW5kIGZpc2hpbmcgYXJlIGFsbG93ZWQgdG8gdmFyeQpqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfbG0gPC0gbG0oc3VydmV5X3VuaXRfY29lZmZpY2llbnQgfiBtZWFuX2Rpc3NpbV9jb2VmLCBkYXRhID0gamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX2R0W3ByZWRfdHlwZSA9PSAiZnVsbCJdKQpzdW1tYXJ5KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9sbSkgI1JeMiAwLjQyCgooamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkIDwtIGdncGxvdChqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHRbcHJlZF90eXBlID09ICJmdWxsIl0pICsKICBnZW9tX2Vycm9yYmFyKGFlcyh4ID0gbWVhbl9kaXNzaW1fY29lZiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGNvbG9yID0gImxpZ2h0Z3JleSIsIGxpbmV3aWR0aCA9IDAuNCkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHhtaW4gPSBtZWFuX2Rpc3NpbV9jb2VmLXNkX2Rpc3NpbSwgeG1heCA9IG1lYW5fZGlzc2ltX2NvZWYrc2RfZGlzc2ltKSwgY29sb3IgPSAibGlnaHRncmV5IiwgbGluZXdpZHRoID0gMC40KSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCB4ID0gbWVhbl9kaXNzaW1fY29lZikpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCB4ID0gbWVhbl9kaXNzaW1fY29lZiksIGNvbG9yID0gImRhcmtncmV5IixsaW5ldHlwZSA9ICJkb3R0ZWQiLCBtZXRob2QgPSAibG0iKSArCiAgZ2VvbV9hYmxpbmUoYWVzKHNsb3BlID0gMSwgaW50ZXJjZXB0ID0gMCkpICsKICBsaW1zKHggPSBjKG1pbihqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHQkcHJlZF9sb3dlciksbWF4KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdCRwcmVkX3VwcGVyKSkpICsKICBsYWJzKHkgPSAiT2JzZXJ2ZWQgzrItZGl2ZXJzaXR5IHRyZW5kIix4ID0gIlByZWRpY3RlZCDOsi1kaXZlcnNpdHkgdHJlbmRcbiIpICsKICB0aGVtZV9jbGFzc2ljKCkKKQoKI2Zpc2hpbmcgY29uc3RhbnQgKGZpc2hpbmcgY29uc3RhbnQ7IHRlbXBlcmF0dXJlIHZhcmllcyBvbmx5KQpqYWNjYXJkX2Zpc2hpbmdfY29uc3RhbnRfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX2xtIDwtIGxtKHN1cnZleV91bml0X2NvZWZmaWNpZW50IH4gbWVhbl9kaXNzaW1fY29lZiwgZGF0YSA9IGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdFtwcmVkX3R5cGUgPT0gImZpc2hpbmdfY29uc3RhbnQiXSkKc3VtbWFyeShqYWNjYXJkX2Zpc2hpbmdfY29uc3RhbnRfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX2xtKSAKI1RlbXBlcmF0dXJlIGFzIGEgcHJlZGljdG9yLCBub3QgZmlzaGluZyA9IFJeMiA9IDAuMjggKGRyb3AgaW4gMTIlIG9mIHZhcmlhbmNlIGV4cGxhaW5lZCB3aGVuIHlvdSBsb3NlIGZpc2hpbmcgYXMgcHJlZGljdG9yKQoKKGphY2NhcmRfZmlzaGluZ19jb25zdGFudF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWQgPC0gZ2dwbG90KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdFtwcmVkX3R5cGUgPT0gImZpc2hpbmdfY29uc3RhbnQiXSkgKwpnZW9tX2Vycm9yYmFyKGFlcyh4ID0gbWVhbl9kaXNzaW1fY29lZiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGNvbG9yID0gImxpZ2h0Z3JleSIsIGxpbmV3aWR0aCA9IDAuNCkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHhtaW4gPSBtZWFuX2Rpc3NpbV9jb2VmLXNkX2Rpc3NpbSwgeG1heCA9IG1lYW5fZGlzc2ltX2NvZWYrc2RfZGlzc2ltKSwgY29sb3IgPSAibGlnaHRncmV5IiwgbGluZXdpZHRoID0gMC40KSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCB4ID0gbWVhbl9kaXNzaW1fY29lZikpICsKICAgIGdlb21fc21vb3RoKGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHggPSBtZWFuX2Rpc3NpbV9jb2VmKSwgY29sb3IgPSAiZGFya2dyZXkiLGxpbmV0eXBlID0gImRvdHRlZCIsIG1ldGhvZCA9ICJsbSIpICsKICBnZW9tX2FibGluZShhZXMoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwKSkgKwogICAgICBsaW1zKHggPSBjKG1pbihqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHQkcHJlZF9sb3dlciksbWF4KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdCRwcmVkX3VwcGVyKSkpICsKICBsYWJzKHkgPSAiT2JzZXJ2ZWQgzrItZGl2ZXJzaXR5IHRyZW5kIix4ID0gIlByZWRpY3RlZCDOsi1kaXZlcnNpdHkgdHJlbmRcbih0ZW1wZXJhdHVyZSB2YXJpZXMgZmlzaGluZyBjb25zdGFudCkiKSArCiAgdGhlbWVfY2xhc3NpYygpCikKCiN0ZW1wIGNvbnN0YW50IChmaXNoaW5nIG9ubHk7IHRlbXBlcmF0dXJlIGNvbnN0YW50KQpqYWNjYXJkX3RlbXBlcmF0dXJlX2NvbnN0YW50X21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9sbSA8LSBsbShzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCB+IG1lYW5fZGlzc2ltX2NvZWYsIGRhdGEgPSBqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfZHRbcHJlZF90eXBlID09ICJ0ZW1wX2NvbnN0YW50Il0pCnN1bW1hcnkoamFjY2FyZF90ZW1wZXJhdHVyZV9jb25zdGFudF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfbG0pICMwLjE4IERyb3AgaW4gMjIlIG9mIHZhcmlhbmNlIGV4cGxhaW5lZCB3aGVuIHlvdSBsb3NlIHRlbXBlcmF0dXJlIGFzIGEgcHJlZGljdG9yCgooamFjY2FyZF90ZW1wZXJhdHVyZV9jb25zdGFudF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWQgPC0gZ2dwbG90KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdFtwcmVkX3R5cGUgPT0gInRlbXBfY29uc3RhbnQiXSkgKwogIGdlb21fZXJyb3JiYXIoYWVzKHggPSBtZWFuX2Rpc3NpbV9jb2VmLCB5bWluID0gbHdyLCB5bWF4ID0gdXByKSwgY29sb3IgPSAibGlnaHRncmV5IiwgbGluZXdpZHRoID0gMC40KSArCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHkgPSBzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCwgeG1pbiA9IG1lYW5fZGlzc2ltX2NvZWYtc2RfZGlzc2ltLCB4bWF4ID0gbWVhbl9kaXNzaW1fY29lZitzZF9kaXNzaW0pLCBjb2xvciA9ICJsaWdodGdyZXkiLCBsaW5ld2lkdGggPSAwLjQpICsKICBnZW9tX3BvaW50KGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHggPSBtZWFuX2Rpc3NpbV9jb2VmKSkgKwogICAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBzdXJ2ZXlfdW5pdF9jb2VmZmljaWVudCwgeCA9IG1lYW5fZGlzc2ltX2NvZWYpLCBjb2xvciA9ICJkYXJrZ3JleSIsbGluZXR5cGUgPSAiZG90dGVkIiwgbWV0aG9kID0gImxtIikgKwogIGdlb21fYWJsaW5lKGFlcyhzbG9wZSA9IDEsIGludGVyY2VwdCA9IDApKSArCiAgICAgIGxpbXMoeCA9IGMobWluKGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdCRwcmVkX2xvd2VyKSxtYXgoamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX2R0JHByZWRfdXBwZXIpKSkgKwogIGxhYnMoeSA9ICJPYnNlcnZlZCDOsi1kaXZlcnNpdHkgdHJlbmQiLHggPSAiUHJlZGljdGVkIM6yLWRpdmVyc2l0eSB0cmVuZFxuKGZpc2hpbmcgdmFyaWVzIHRlbXBlcmF0dXJlIGNvbnN0YW50KSIpICsKICB0aGVtZV9jbGFzc2ljKCkKKQoKI2JvdGggdGVtcGVyYXR1cmUgYW5kIGZpc2ggaGVsZCBjb25zdGFudApqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfdGVtcGZpc2hjb25zdGFudGluc3VydmV5X2xtIDwtIGxtKHN1cnZleV91bml0X2NvZWZmaWNpZW50IH4gbWVhbl9kaXNzaW1fY29lZiwgZGF0YSA9IGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdFtwcmVkX3R5cGUgPT0gImZpc2hpbmdfYW5kX3RlbXBfY29uc3RhbnQiXSkKc3VtbWFyeShqYWNjYXJkX2Zpc2hpbmdfdGVtcF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWRfdGVtcGZpc2hjb25zdGFudGluc3VydmV5X2xtKSAjJTExIAoKKGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF90ZW1wZmlzaGNvbnN0YW50aW5zdXJ2ZXkgPC0gZ2dwbG90KGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdFtwcmVkX3R5cGUgPT0gImZpc2hpbmdfYW5kX3RlbXBfY29uc3RhbnQiXSkgKwpnZW9tX2Vycm9yYmFyKGFlcyh4ID0gbWVhbl9kaXNzaW1fY29lZiwgeW1pbiA9IGx3ciwgeW1heCA9IHVwciksIGNvbG9yID0gImxpZ2h0Z3JleSIsIGxpbmV3aWR0aCA9IDAuNCkgKwogIGdlb21fZXJyb3JiYXJoKGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHhtaW4gPSBtZWFuX2Rpc3NpbV9jb2VmLXNkX2Rpc3NpbSwgeG1heCA9IG1lYW5fZGlzc2ltX2NvZWYrc2RfZGlzc2ltKSwgY29sb3IgPSAibGlnaHRncmV5IiwgbGluZXdpZHRoID0gMC40KSArCiAgZ2VvbV9wb2ludChhZXMoeSA9IHN1cnZleV91bml0X2NvZWZmaWNpZW50LCB4ID0gbWVhbl9kaXNzaW1fY29lZikpICsKICAgIGdlb21fc21vb3RoKGFlcyh5ID0gc3VydmV5X3VuaXRfY29lZmZpY2llbnQsIHggPSBtZWFuX2Rpc3NpbV9jb2VmKSwgY29sb3IgPSAiZGFya2dyZXkiLGxpbmV0eXBlID0gImRvdHRlZCIsIG1ldGhvZCA9ICJsbSIpKwogIGdlb21fYWJsaW5lKGFlcyhzbG9wZSA9IDEsIGludGVyY2VwdCA9IDApKSArCiAgICAgIGxpbXMoeCA9IGMobWluKGphY2NhcmRfZmlzaGluZ190ZW1wX21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9kdCRwcmVkX2xvd2VyKSxtYXgoamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX2R0JHByZWRfdXBwZXIpKSkgKwogIGxhYnMoeSA9ICJPYnNlcnZlZCDOsi1kaXZlcnNpdHkgdHJlbmQiLHggPSAiUHJlZGljdGVkIM6yLWRpdmVyc2l0eSB0cmVuZFxuKGZpc2hpbmcgYW5kIHRlbXBlcmF0dXJlIGNvbnN0YW50KSIpICsKICB0aGVtZV9jbGFzc2ljKCkKKQoKCiNtZXJnZQpqYWNjYXJkX2Zpc2hpbmdfc2J0X21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9tZXJnZSA8LSBwbG90X2dyaWQoamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkICsgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMC4xLDAuMywwLjEsMC4xKSwiY20iKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGphY2NhcmRfZmlzaGluZ19jb25zdGFudF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWQgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjEsMC4zLDAuMSwwLjEpLCJjbSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgamFjY2FyZF90ZW1wZXJhdHVyZV9jb25zdGFudF9tb2RlbF9vYnNlcnZlZF9wcmVkaWN0ZWQgKyB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYygwLjEsMC4zLDAuMSwwLjEpLCJjbSIpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgamFjY2FyZF9maXNoaW5nX3RlbXBfbW9kZWxfb2JzZXJ2ZWRfcHJlZGljdGVkX3RlbXBmaXNoY29uc3RhbnRpbnN1cnZleSArIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDAuMSwwLjMsMC4xLDAuMSksImNtIikpLCBuY29sID0gMiwgbGFiZWxzID0gYygiYS4iLCJiLiIsImMuIiwiZC4iKSkKCmdnc2F2ZShqYWNjYXJkX2Zpc2hpbmdfc2J0X21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9tZXJnZSwgcGF0aCA9IGhlcmU6OmhlcmUoImZpZ3VyZXMiKSxmaWxlbmFtZSA9ICJqYWNjYXJkX2Zpc2hpbmdfc2J0X21vZGVsX29ic2VydmVkX3ByZWRpY3RlZF9tZXJnZS5qcGciLCBoZWlnaHQgPTYsIHdpZHRoID0gOCkKCgpgYGAKCkxldCdzIHZpc3VhbGl6ZSBtb2RlbCBjb2VmZmljaWVudHMgd2l0aCB0ZW1wZXJhdHVyZSBhbmQgZmlzaGluZyAoc2ltaWxhciB0byBmaWd1cmUgMikKbW9kZWxfYXZnX3ZhbHVlcwpgYGB7cn0KbW9kZWxfYXZnX3ZhbHVlcwoKaW50ZXJhY3Rpb25fYXZnX21vZGVsX2NvZWYgPC0gbW9kZWxfYXZnX3ZhbHVlc1tjKDUsMzc6OTkpLC4oY29lZl9uYW1lLCBjb2VmLCBzZSldCgojaW5zZXJ0IEFJCmludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmWzE6MixzdXJ2ZXlfdW5pdCA6PSAiQUkiXVsxOjIsY29lZl90cnVlIDo9IGNvZWZdWzE6MixwcmVkaWN0b3IgOj0gYygiUmVsYXRpdmUgZmlzaGluZyBjYXRjaCIsIk1pbmltdW0gdGVtcGVyYXR1cmUiKV0KCiNPdGhlciBzdW1tZWRfdG9ubmVzX3NjYWxlZF9ieXJlZwppbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZlszOjMzLHN1cnZleV91bml0IDo9IHN1YnN0cihjb2VmX25hbWUsIDM5LCBzdHJfbGVuZ3RoKGNvZWZfbmFtZSkpXVszOjMzLGNvZWZfdHJ1ZSA6PSBpbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZlsxLGNvZWZfdHJ1ZV0rY29lZl1bMzozMyxwcmVkaWN0b3IgOj0gIlJlbGF0aXZlIGZpc2hpbmcgY2F0Y2giXQoKI090aGVyIHllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsCmludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmWzM0OjY0LHN1cnZleV91bml0IDo9IHN1YnN0cihjb2VmX25hbWUsIHN0cl9sZW5ndGgoInN1cnZleV91bml0IikrMSwgc3RyX2xlbmd0aChjb2VmX25hbWUpLXN0cl9sZW5ndGgoInllYXJseV9taW5fYnlwb2ludF9hdmcuc2NhbGVkYWNyb3NzYWxsIiktMSldWzM0OjY0LGNvZWZfdHJ1ZSA6PSBpbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZlsyLGNvZWZfdHJ1ZV0rY29lZl1bMzQ6NjQscHJlZGljdG9yIDo9ICJNaW5pbXVtIHRlbXBlcmF0dXJlIl0KCiNyZW9yZGVyIHRlbXBlcmF0dXJlIGFuZCBmaXNoaW5nCmludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmWyxwcmVkaWN0b3IgOj0gZmFjdG9yKHByZWRpY3RvciwgbGV2ZWxzID0gYygiTWluaW11bSB0ZW1wZXJhdHVyZSIsIlJlbGF0aXZlIGZpc2hpbmcgY2F0Y2giKSldCgojbGluayBmb3IgZnVsbCBzdXJ2ZXkgbmFtZQppbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZiA8LSBjb2xvcl9saW5rW2ludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmLCBvbiA9ICJzdXJ2ZXlfdW5pdCJdCgojcmVvcmRlciBieSBzdXJ2ZXlfdW5pdAppbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZlssU3VydmV5X05hbWVfU2Vhc29uIDo9IHJlb3JkZXIoU3VydmV5X05hbWVfU2Vhc29uLCBzdXJ2ZXlfdW5pdCwgZGVjcmVhc2luZyA9IFRSVUUpXQoKI21hcmsgc2lnbmlmaWNhbmNlCmludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmWyxTaWduaWZpY2FudCA6PSBpZmVsc2UoKGNvZWZfdHJ1ZS1zZSA+IDAgJiBjb2VmX3RydWUrc2UgPiAwKSB8IChjb2VmX3RydWUtc2UgPCAwICYgY29lZl90cnVlK3NlIDwgMCksVCxGKV0KCgojUGxvdCBib3RoCnNidF9maXNoaW5nX2F2Z19tb2RlbF9jb2VmIDwtIGdncGxvdCgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiKSArCmdlb21fcG9pbnQoZGF0YSA9IGludGVyYWN0aW9uX2F2Z19tb2RlbF9jb2VmLCBhZXMoeCA9IFN1cnZleV9OYW1lX1NlYXNvbiwgeSA9IGNvZWZfdHJ1ZSwgY29sb3IgPSBTaWduaWZpY2FudCkpICsgIApnZW9tX2Vycm9yYmFyKGRhdGEgPSBpbnRlcmFjdGlvbl9hdmdfbW9kZWxfY29lZiwgYWVzKHggPSBTdXJ2ZXlfTmFtZV9TZWFzb24sIHltaW4gPSBjb2VmX3RydWUtc2UsIHltYXggPSBjb2VmX3RydWUrc2UsIGNvbG9yID0gU2lnbmlmaWNhbnQpLCB3aWR0aCA9IDApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGFya2dyZXkiLCJibGFjayIpKSArCmZhY2V0X3dyYXAofnByZWRpY3Rvciwgc2NhbGVzID0gImZyZWVfeCIpICsKc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSByZXYpICsKICBsYWJzKHkgPSAiQ29lZmZpY2llbnQiLCB4ID0gIiIpICsKY29vcmRfZmxpcCgpICsKdGhlbWVfY2xhc3NpYygpCiAgCgoKYGBgClBsb3QgYWxsIG90aGVyIGNvZWZmaWNpZW50cyBpbiBhdmVyYWdlZCBtb2RlbApgYGB7cn0KbW9kZWxfYXZnX3ZhbHVlcy5ub25maXNob3J0ZW1wIDwtIG1vZGVsX2F2Z192YWx1ZXNbYygyLDMsNCwxMDA6MTA0KSxdCgojbWFyayBzaWduaWZpY2FuY2UKbW9kZWxfYXZnX3ZhbHVlcy5ub25maXNob3J0ZW1wWyxTaWduaWZpY2FudCA6PSBpZmVsc2UoKGNvZWYtc2UgPiAwICYgY29lZitzZSA+IDApIHwgKGNvZWYtc2UgPCAwICYgY29lZitzZSA8IDApLFQsRildCgojbW9yZSBoZWxwZnVsIG5hbWVzIGZvciB2YXJpYWJsZXMKbW9kZWxfYXZnX3ZhbHVlcy5ub25maXNob3J0ZW1wWyxWYXJpYWJsZSA6PSBjKCJBcmVhIiwiSnVsaWFuIGRheSIsIlNwZWNpZXMgY291bnQiLCJOdW1iZXIgb2YgdG93cyIsIkxhdGl0dWRlIHJhbmdlIiwiRGVwdGgiLCJMYXRpdHVkZSIsIkRlcHRoIHJhbmdlIildCgojbWFrZSBmYWN0b3Igd2l0aCBvcmRlcgptb2RlbF9hdmdfdmFsdWVzLm5vbmZpc2hvcnRlbXBbLFZhcmlhYmxlIDo9IGZhY3RvcihWYXJpYWJsZSwgbGV2ZWxzID0gYygiQXJlYSIsIkp1bGlhbiBkYXkiLCJTcGVjaWVzIGNvdW50IiwiTnVtYmVyIG9mIHRvd3MiLCJEZXB0aCIsIkRlcHRoIHJhbmdlIiwiTGF0aXR1ZGUiLCJMYXRpdHVkZSByYW5nZSIpKV0KCgojcGxvdAphbGxfYXZnX21vZGVsX2NvZWYgPC0gZ2dwbG90KCkgKyAKZ2VvbV9wb2ludChkYXRhID0gbW9kZWxfYXZnX3ZhbHVlcy5ub25maXNob3J0ZW1wLCBhZXMoeCA9IFZhcmlhYmxlLCB5ID0gY29lZiwgY29sb3IgPSBTaWduaWZpY2FudCkpICsgIApnZW9tX2Vycm9yYmFyKGRhdGEgPSBtb2RlbF9hdmdfdmFsdWVzLm5vbmZpc2hvcnRlbXAsIGFlcyh4ID0gVmFyaWFibGUsIHltaW4gPSBjb2VmLXNlLCB5bWF4ID0gY29lZitzZSwgY29sb3IgPSBTaWduaWZpY2FudCksIHdpZHRoID0gMCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrZ3JleSIsImJsYWNrIikpICsKZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwpzY2FsZV94X2Rpc2NyZXRlKGxpbWl0cyA9IHJldikgKwogIGxhYnMoeSA9ICJDb2VmZmljaWVudCIsIHggPSAiXG5cblxuIikgKwpjb29yZF9mbGlwKCkgKwp0aGVtZV9jbGFzc2ljKCkKCiNwbG90CmFsbF9idXRfbGF0X2F2Z19tb2RlbF9jb2VmIDwtIGdncGxvdCgpICsgCmdlb21fcG9pbnQoZGF0YSA9IG1vZGVsX2F2Z192YWx1ZXMubm9uZmlzaG9ydGVtcFtWYXJpYWJsZSA9PSAiTGF0aXR1ZGUiXSwgYWVzKHggPSBWYXJpYWJsZSwgeSA9IGNvZWYsIGNvbG9yID0gU2lnbmlmaWNhbnQpKSArICAKZ2VvbV9lcnJvcmJhcihkYXRhID0gbW9kZWxfYXZnX3ZhbHVlcy5ub25maXNob3J0ZW1wW1ZhcmlhYmxlID09ICJMYXRpdHVkZSJdLCBhZXMoeCA9IFZhcmlhYmxlLCB5bWluID0gY29lZi1zZSwgeW1heCA9IGNvZWYrc2UsIGNvbG9yID0gU2lnbmlmaWNhbnQpLCB3aWR0aCA9IDApICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiZGFya2dyZXkiLCJibGFjayIpKSArCmdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsKc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSByZXYpICsKICBsYWJzKHkgPSAiQ29lZmZpY2llbnQiLCB4ID0gIk1vZGVsIHZhcmlhYmxlIikgKwpjb29yZF9mbGlwKCkgKwp0aGVtZV9jbGFzc2ljKCkKCiNwbG90CmxhdF9hdmdfbW9kZWxfY29lZiA8LSBnZ3Bsb3QoKSArIApnZW9tX3BvaW50KGRhdGEgPSBtb2RlbF9hdmdfdmFsdWVzLm5vbmZpc2hvcnRlbXBbVmFyaWFibGUgIT0gIkxhdGl0dWRlIl0sIGFlcyh4ID0gVmFyaWFibGUsIHkgPSBjb2VmLCBjb2xvciA9IFNpZ25pZmljYW50KSkgKyAgCmdlb21fZXJyb3JiYXIoZGF0YSA9IG1vZGVsX2F2Z192YWx1ZXMubm9uZmlzaG9ydGVtcFtWYXJpYWJsZSAhPSAiTGF0aXR1ZGUiXSwgYWVzKHggPSBWYXJpYWJsZSwgeW1pbiA9IGNvZWYtc2UsIHltYXggPSBjb2VmK3NlLCBjb2xvciA9IFNpZ25pZmljYW50KSwgd2lkdGggPSAwKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImRhcmtncmV5IiwiYmxhY2siKSkgKwpnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArCnNjYWxlX3hfZGlzY3JldGUobGltaXRzID0gcmV2KSArCiAgbGFicyh5ID0gIkNvZWZmaWNpZW50IiwgeCA9ICJNb2RlbCB2YXJpYWJsZSIpICsKY29vcmRfZmxpcCgpICsKdGhlbWVfY2xhc3NpYygpCgojbWVyZ2UgaW50byBzaW5nbGUgcGxvdAoKbW9kZWxfY29lZl9zdW1tYXJ5X3NidF9qYWNjYXJkIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChzYnRfZmlzaGluZ19hdmdfbW9kZWxfY29lZit0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibnVsbCIsIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSksYWxsX2F2Z19tb2RlbF9jb2VmK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJudWxsIiksIG5jb2wgPSAxLCBsYWJlbHMgPSBjKCIgIGEuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYi4iLCIgICAgICAgIGMuIiksIGxhYmVsX3kgPSAwLjk5LCByZWxfaGVpZ2h0cyA9IGMoMywxKSkKCmdnc2F2ZShtb2RlbF9jb2VmX3N1bW1hcnlfc2J0X2phY2NhcmQsIHBhdGggPSBoZXJlOjpoZXJlKCJmaWd1cmVzIiksZmlsZW5hbWUgPSAibW9kZWxfY29lZl9zdW1tYXJ5X3NidF9qYWNjYXJkLmpwZyIsIGhlaWdodCA9IDYuNSwgd2lkdGggPSA4LCB1bml0ID0gImluIikKCgpgYGAKCg==